The macros print!
, println!
, eprint!
, eprintln!
, write!
, writeln!
and format!
are a special case and implicitly take a reference to any arguments to be formatted.
These macros do not behave as normal functions and macros do for reasons of convenience; the fact that they take references silently is part of that difference.
fn main() {
let x = 5;
println!("{}", x);
}
Run it through rustc -Z unstable-options --pretty expanded
on the nightly compiler and we can see what println!
expands to:
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;
fn main() {
let x = 5;
{
::std::io::_print(::core::fmt::Arguments::new_v1(
&["", "
"],
&match (&x,) {
(arg0,) => [::core::fmt::ArgumentV1::new(
arg0,
::core::fmt::Display::fmt,
)],
},
));
};
}
Tidied further, it’s this:
use std::{fmt, io};
fn main() {
let x = 5;
io::_print(fmt::Arguments::new_v1(
&["", "
"],
&[fmt::ArgumentV1::new(&x, fmt::Display::fmt)],
// ^^
));
}
Note the &x
.
If you write println!("{}", &x)
, you are then dealing with two levels of references; this has the same result because there is an implementation of std::fmt::Display
for &T
where T
implements Display
(shown as impl<'a, T> Display for &'a T where T: Display + ?Sized
) which just passes it through. You could just as well write &&&&&&&&&&&&&&&&&&&&&&&x
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…