Rust 的 println! 是如何工作的?宏执行取消引用?
How Does Rust's println! macro perform dereferencing?
println!
宏可以处理值和引用,而无需显式解除引用。
首先,创建一个向量
let v = vec![0, 2, 3, -4];
正在打印来自 vec.iter
的引用
for x in v.iter() {
println!("x: {}", x);
}
打印来自 vec.iter
的解除引用的元素
for x in v.iter() {
println!("x: {}", *x);
}
正在打印来自 vec
的值
for x in v {
println!("x: {}", x);
}
案例1中的内部解引用是如何完成的?
我内部知道 println!
进行了另一个宏调用,但链中的最后一个宏 format_args!
是在编译器级别实现的,我没有看到它。
macro_rules! println {
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! print {
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}
macro_rules! format_args {
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
}
这里重要的是,在格式字符串中使用 {}
会在传递的值上调用 Display
特征。
正如预期的那样,the i32 type 实现了 Display
,这就是让您的案例 #2 和案例 #3 起作用的原因。因为他们得到的是标准 i32
值,而不是参考值,所以一切正常。
对于您的案例 #1,x
将是 &i32
,这似乎是您问题的核心。答案在 the Display
trait 中。显示包含以下内容:
impl<'a, T> Display for &'a T
where
T: Display + ?Sized
表示 "for the reference type of T
, implement Display
if T
implements Display
"。这意味着因为 i32
实现了 Display
,引用类型也自动实现了它。
这里编译器没有进行特殊的类型处理。编译器实现的代码将该责任传递给 Display
特性的实现。
println!
宏可以处理值和引用,而无需显式解除引用。
首先,创建一个向量
let v = vec![0, 2, 3, -4];
正在打印来自
的引用vec.iter
for x in v.iter() { println!("x: {}", x); }
打印来自
的解除引用的元素vec.iter
for x in v.iter() { println!("x: {}", *x); }
正在打印来自
的值vec
for x in v { println!("x: {}", x); }
案例1中的内部解引用是如何完成的?
我内部知道 println!
进行了另一个宏调用,但链中的最后一个宏 format_args!
是在编译器级别实现的,我没有看到它。
macro_rules! println {
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! print {
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}
macro_rules! format_args {
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
}
这里重要的是,在格式字符串中使用 {}
会在传递的值上调用 Display
特征。
正如预期的那样,the i32 type 实现了 Display
,这就是让您的案例 #2 和案例 #3 起作用的原因。因为他们得到的是标准 i32
值,而不是参考值,所以一切正常。
对于您的案例 #1,x
将是 &i32
,这似乎是您问题的核心。答案在 the Display
trait 中。显示包含以下内容:
impl<'a, T> Display for &'a T
where
T: Display + ?Sized
表示 "for the reference type of T
, implement Display
if T
implements Display
"。这意味着因为 i32
实现了 Display
,引用类型也自动实现了它。
这里编译器没有进行特殊的类型处理。编译器实现的代码将该责任传递给 Display
特性的实现。