The article says that the ref before the parameter name is used to get the parameter reference, so why is the pointer address printed by `&` different?

fn main() {
    let s = S { i: 42 };
    println!("{:p}", &s);   // 0x7fff4c7147ec
    
    f2(&s); // 0x7fff4c7147ec
    f2(&s); // 0x7fff4c7147ec
    
    f(s);   // 0x7fff4c71476c
}

Expected:

f(s); This line should output 0x7fff4c7147ec, why is it different?

playground link

Where did I understand it wrong?

s is created in main's stack.

On the first println, you get 0x7fff4c7147ec.

On the second println, which runs inside f2, you get 0x7fff4c7147ec again, because you took a reference to s, same as you did in the previous println.

The third println is identical to the second.

The fourth println is run inside of f. f is declared as such:

fn f(ref _s: S);

However, the ref pattern is only something that's exposed to the function's contents. To any caller, the signature is:

fn f(_s: S);

Indeed, a ref pattern moves the value, and then takes a reference to it.

It's essentially syntactical sugar for the following:

fn f(_s: S) {
    let _s = &_s;
    // The rest of your function...
}

And so we get a different address because now it's been moved into a different stack, the one belonging to f instead of main. However, it's completely plausible for them to print the same number, since certain optimizations will completely optimize out the need for a move.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.