Why do mutable raw pointers to zero-sized types allocate real memory?

Here is my code:

fn main()
{
    let stk_ptr1: *mut EmptyType1 = &mut EmptyType1;
    let stk_ptr2: *mut EmptyType2 = &mut EmptyType2;
    let stk_ptr3: *mut EmptyType3 = &mut EmptyType3;

    println!("{:p}", stk_ptr1);
    println!("{:p}", stk_ptr2);
    println!("{:p}", stk_ptr3);   
}

struct EmptyType1;
struct EmptyType2;
struct EmptyType3;

The above code snippet prints the following:

0x7ffe88253f60
0x7ffe88253f70
0x7ffe88253f80

But if the pointers were not mutable pointers it prints the same memory address three times like:

0x55f14834805b
0x55f14834805b
0x55f14834805b

And if we take reference to mentioned zero-sized types it prints the same memory addresses. Here is the code:

fn main()
{
    let ref_emp = &EmptyType;
    let ref_emp2 = &EmptyType2;
    let ref_emp3 = &EmptyType3;

    println!("{:p}", ref_emp);
    println!("{:p}", ref_emp2);
    println!("{:p}", ref_emp3);
}

struct EmptyType;
struct EmptyType2;
struct EmptyType3;

And this code snippet prints the following:

0x560cfd298010
0x560cfd298010
0x560cfd298010
2 Likes

I guess (haven't verified) that shared references get promoted to statics and thus occupy no place, but mutable references don't and rather get allocaed.

Interesting observation but it's nothing intrinsic; some lack of optimization going on. They have the same address under release mode. Addresses of ZSTs / usize values of references or pointers to ZSTs don't really mean much, since the ZSTs don't actually occupy any memory (e.g. it's impossible for the references to alias).

3 Likes

If you turn on release mode, they get the same address.

3 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.