So my question about the code below comes down to: why does 0x7fff0b5e2e74 appear twice in the output?
fn main () {
let mut a = "Rogers".to_string();
let mut b = 3;
println!("{:p}", &a);
println!("{:p}", &b);
fn nothing(snape:String) -> String {
nothing2(snape)
}
fn nothing2(y:String) -> String {
y
}
fn nada(snape:i32)-> i32 {
println!("{:p}", &snape);
nada2(snape)
}
fn nada2(y:i32)-> i32 {
println!("{:p}", &y);
y
}
a = nothing(a);
b = nada(b);
println!("{:p}", &a);
println!("{:p}", &b);
// I expected b after the call to nada to have a new address because i32 is copy.
// Is this a compiler optimization or am I missing something?
// Compiling playground v0.0.1 (/playground)
// Finished dev [unoptimized + debuginfo] target(s) in 0.55s
// Running `target/debug/playground`
// Standard Output
// 0x7fff0b5e2e50
// 0x7fff0b5e2e74
// 0x7fff0b5e2dac
// 0x7fff0b5e2d4c
// 0x7fff0b5e2e50
// 0x7fff0b5e2e74
}
let mut b = 3;
println!("&b {:p}", &b);
fn nada(snape:i32)-> i32 { /* ... */ }
b = nada(b);
println!("&b {:p}", &b);
// I expected b after the call to nada to have a new address because i32 is copy.
// Is this a compiler optimization or am I missing something?
When you passed b to nada you passed a copy, so the local b variable was not uninitialized. You didn't move the b variable. Then you overwrote b with the result. But you still didn't move b.
I thought a "copy" passed to nada would have a different address than the original. And indeed the addresses printed from within nada and nada2are different. So why does b end up with the original address at the end of main? It was assigned the return value from nada. My results seems like i32 behaves the same as String.
Thinking about it. I now understand you are saying b in main always has the same address. It's the value that is changing. So even if I completely returned something different from nada, my println! results would be the same. The only way I could change the "address" of b in main would be by another let b = ... statement. I verified that. Thanks for clearing up a not-so-bright experiment on my part.
I think you figured it out while I was writing the below, but since I wrote it, I'll post it anyway.
Variable b in main occupies a position on the stack. [1]
b = nada(b);
// ^ Part 1
A copy of b is made to elsewhere on the stack for the call to nada.
b = nada(b);
// ^^^^^ ^ Part 2
nada executes and returns a value somehow, let's say in a register.
b = nada(b);
// ^^^^ Part 3
The returned value is copied into b's stack location.
b's stack location never changed.
The values that get passed around don't have some sort of inherent address identity that goes with them via copies and moves. Not every value is boxed with a fixed address.
Well it doesn't have to, it could be in a register or completely optimized out in a typical program, but you're basically forcing it to be on the stack by examining its address. âŠī¸