Pointer::offset_from for pointer to a structure

I would like to calculate the offset difference between pointer, it is fine for u8 type, but it fails to return correct value for structure.

#![feature(ptr_offset_from)]
#![allow(unused)]
#![allow(unused_variables)]

#[derive(Default, Debug, Clone)]
pub struct Node {
    pub key: u64,
    pub value: u32,
    pub color: u16,
    pub number: u8,
}

fn main() {

    println!("Node::size = {}", std::mem::size_of::<Node>());

    let a: Vec<u8> = vec![2, 3, 4];

    let ptr0: *const u8 = &a[0];
    let ptr2: *const u8 = &a[2];

    unsafe { println!("offset_from 0 = {}", ptr2.offset_from(ptr0)) }

    let ptr0: *const Node = &a[0] as *const u8 as *const Node;
    let ptr2: *const Node = &a[2] as *const u8 as *const Node;

    unsafe { println!("offset_from 0 = {}", ptr2.offset_from(ptr0)) }

}

output

Node::size = 16
offset_from 0 = 2
offset_from 0 = 0 
// expect
Node::size = 16
offset_from 0 = 2
offset_from 0 = 2

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=6892b987092a017abb5db74d41f6895c

any workaround for this?

Note: This is a nightly-only experimental API, is this the reason that this output appears?

Please read the whole documents carefully when you write the unsafe code. Safe Rust is always safe, but unsafe Rust is only usable if you satisfy all the conditions the documents and the language specification provides.

Regarding the document, this is UB, specifically violating the third condition of the Safety section. So you cannot expect stable result on this operation. Moreover, the compiler may wipe out the whole code for the sake of the optimization.

Is there any way to calculate the address difference of struct ?

Of course it can be calculated, simply by converting both addresses to usize integers and subtracting one from the other. What you can't do is fabricate an address from that integer result and then attempt to use it as a reference, because that step is almost always UB.

1 Like

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.