Reference cast to raw pointer

How to get a raw pointer to another raw pointer

fn main() {
    
    let i = 123;
    let p1 = &i;
    let p2 = &p1;

    let raw1 = p1 as *const i32;

    // error code
    let raw2 = p2 as **const i32;
    
    println!("{:p}", raw1);
    println!("{:p}", raw2);
}

print

error: expected mut or const in raw pointer type
   --> demo\src\bin\point.rs:128:22
    |
128 |     let raw2 = p2 as **const i32;
    |                      ^ expected mut or const in raw pointer type
    |
    = help: use `*mut T` or `*const T` as appropriate

error[E0606]: casting `&&i32` as `*const *const i32` is invalid
   --> demo\src\bin\point.rs:128:16
    |
128 |     let raw2 = p2 as **const i32;
    |                ^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
let raw2 = p1 as *const _ as *const *const i32;

This first turns p1 into a *const &i32 and then casts that into a *const *const i32.

When using such a cast pointer (in unsafe code), you’ll have to be cautious in general since it’s possible to cast *const S into *const T for any types S and T. Since *const i32 and &i32 have the same layout, it should be safe to dereference raw2 obtained in this fashion though.

It would be more elegant and safer to just do it directly, one step at a time:

let raw1 = p1 as *const _;
let raw2 = &raw1 as *const _;

(That is, unless you specifically want p2 to point to p1 directly, but that seems like a weird requirement, of which the relevance is not apparent from your example code snippet.)

2 Likes