Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Raw pointer of array and pointer of slice in Rust

I’m trying to better understand Rust’s raw pointers, and I thought the following code would fail (sorry for possible UB) [Playground]:

fn main() {
    println!("size of * const u32 ->{}", std::mem::size_of::<* const u32>());
    println!("size of * const [u32;13] ->{}", std::mem::size_of::<* const [u32;13]>());
    println!("size of * const [u32] ->{}", std::mem::size_of::<* const [u32]>());
    let x = 1u32;
    let arr = [1,2,3,4,5,6,7,8, 9, 10, 11, 12, 13u32];
    let px: * const u32 = &x;
    let parr: * const [u32;13] = &arr;
    let slice: &[u32] = &arr;
    let pslice: * const [u32] = slice;
    unsafe { println!("px -> {:?}", px.as_ref()) };
    unsafe { println!("parr -> {:?}", parr.as_ref()) };
    unsafe { println!("pslice -> {:?}", pslice.as_ref()) };
    //
    println!("How could this work:");
    let pslice2: * const [u32] = parr; // How could this work ?
    unsafe { println!("pslice2 -> {:?}", pslice2.as_ref()) }; // How could this work ?
}

But it worked even with miri:

Standard Error

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 1.16s
     Running `/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/playground`

Standard Output

size of * const u32 ->8
size of * const [u32;13] ->8
size of * const [u32] ->16
px -> Some(1)
parr -> Some([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
pslice -> Some([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
How could this work:
pslice2 -> Some([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])

I am not surprised with the fact that slice pointer is sized 16 while array pointer is sized 8, because the type does not include the size of the data. But why code let pslice2: * const [u32] = parr;, following let parr: * const [u32;13] = &arr;, is accepted and why pslice.as_ref() produce some data?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

I guess it could seem weird to initialise pslice2, a fat pointer (address+size), from parr, a simple pointer (address only), because the size information missing in parr is necessary for pslice2.

But this size information is known by the compiler (as a constant, not stored anywhere in a variable); that’s why parr enables accessing all the elements in the array.
Then, during the initialisation of pslice2, the «missing» size information is simply provided by the compiler (the constant is stored inside the fat pointer).
Once it’s done, pslice2 is a fully functional fat pointer (address+size) which enables accessing all the elements in the array.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading