I have this struct defined in my code:
#[repr(align(4))]
struct MetaDataDefn {
cncVersion: i32,
toDriverBufferLength: i32,
toClientsBufferLength: i32,
counterMetadataBufferLength: i32,
counterValuesBuferLength: i32,
clientLivenessTimeout: i64,
startTimestamp: i64,
pid: i64
}
I have a function that takes a raw pointer to a chunk of memory, where the first bytes correspond to a struct with the same layout. I thought that if I cast the u8 pointer to a struct pointer, I'd get the same result as if I did a reinterpret_cast in C++. However, I think that's not the case, and I'm a bit confused about what's going on here. This is the body of the function (the pointer that the function receives is cncFilePtr):
let metadata = unsafe { cncFilePtr as *mut MetaDataDefn };
// This works
let cncVersion = unsafe { (*(cncFilePtr as *mut i32)) };
println!("CNC Version: {}", cncVersion);
//This prints a different number than the previous code
println!("CNC version (other way): {}", unsafe { (*metadata).cncVersion });
As you can see, casting the first 4 bytes to a i32 and then printing the result gives a different result than casting the whole thing to MetaDataDefn and accessing the first member, which is of type i32 (my understanding is that both approaches should give the same result)
My question is: why it's not the same result? is casting pointers in Rust not the same as reinterpret_cast in C++ (I come from a C++ background)?
Normally, Rust makes no guarantees about the way that a struct is represented in memory. It can reorder fields to make them pack more tightly, and could theoretically even optimise the field order based on how your application actually accesses them.
You can fix the order, to behave like C, by adding the #[repr(C)]
attribute:
#[repr(C)]
#[repr(align(4))]
struct MetaDataDefn { ... }
With that, both pointers will give the same result because this guarantees that cncVersion
appears first.