When does dereferencing a pointer create a copy?

Why does &mut (*pointer) create a reference to the original memory behind pointer, while &mut { *pointer } creates a reference to a copy?

#[derive(Copy, Clone)]
struct MyStruct {
    num: u32,
}

fn main() {
    let mut my_struct = MyStruct { num: 42 };
    let pointer = &mut my_struct as *mut MyStruct;
    let ref_to_orig = unsafe { &mut (*pointer) };
    ref_to_orig.num += 100;
    println!("{}", my_struct.num); // prints "142"
    let ref_to_copy = unsafe { &mut { *pointer } };
    ref_to_copy.num += 100;
    println!("{}", my_struct.num); // still prints "142"
}

(Context: I need to understand this because I'm trying to work with Apple's CoreAudio C API, which uses callbacks. I need to write a callback in Rust conforming to a C API which takes a void* as an argument. The void* will be a pointer to a struct, whose fields the callback needs to modify. Updating the fields of a local copy would be pointless.)

(Playground)

(*pointer) is a place expression, while { *pointer } is a value expression.

You can read more about their behavior in this case in the Rust reference: Expressions - The Rust Reference

1 Like

Interestingly though, neither that page nor the page on Grouped expressions specify what type of expression a grouped expression is.

It is neither (and both): (expr) can be either a place expression or a value expression, depending on what expr is.

(*pointer) is a place expression because *pointer is a place expression. ({*pointer}) would be a value expression. The parentheses do nothing but group.

You might also be interested in this article: Stuff the Identity Function Does (in Rust)

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.