Reputation: 1778
It seems the layout of a struct is not linear. Looks like fields of struct in memory are not in the same order as they are written into the definition of the structure. Is there a way to ask the compiler to preserve the order of fields? What other solution of the problem can you suggest? Any reading?
use std::borrow::Borrow;
fn main()
{
let header = ObjectHeader
{
x : 1,
h : 2,
a : 3,
f : 4,
w : 5,
body : (),
};
let object = header.form();
let borrowed_header : &ObjectHeader = object.borrow();
dbg!( borrowed_header );
}
//
#[ derive( Debug, Clone ) ]
pub struct ObjectGeneric< Body >
{
pub x : i64,
pub h : u32,
pub a : u8,
pub f : u16,
pub w : u32,
pub body : Body,
}
pub type ObjectHeader = ObjectGeneric< () >;
impl ObjectHeader
{
pub fn form( self ) -> Object
{
let body = ObjectBody { j : 10 };
Object
{
x : self.x,
h : self.h,
a : self.a,
f : self.f,
w : self.w,
body,
}
}
}
#[ derive( Debug, Clone ) ]
pub struct ObjectBody
{
pub j : u32,
}
pub type Object = ObjectGeneric< ObjectBody >;
//
impl Borrow< ObjectHeader > for Object
{
fn borrow<'a>( &'a self ) -> &'a ObjectHeader
{
unsafe
{
dbg!( &self );
let result = std::mem::transmute::< &'a Object, &'a ObjectHeader >( self );
dbg!( &result );
result
}
}
}
//
Output:
[src/main.rs:69] &self = ObjectGeneric {
x: 1,
h: 2,
a: 3,
f: 4,
w: 5,
body: ObjectBody {
j: 10,
},
}
[src/main.rs:71] &result = ObjectGeneric {
x: 1,
h: 2,
a: 0,
f: 10,
w: 5,
body: (),
}
[src/main.rs:17] borrowed_header = ObjectGeneric {
x: 1,
h: 2,
a: 0,
f: 10,
w: 5,
body: (),
}
Upvotes: 1
Views: 251
Reputation: 124
In Rust the order of fields in compiled program can be different to order in code. I think in practice compiler reorders fields to reduce padding
You can use directive repr(C)
to save original order of fields
#[repr(C)]
===
Official documentation declares that for default layout, the order of fields is not specified :
With the exception of the guarantees provided below, the default layout of structs
is not specified.
And, you can read counteropinions for saving layout and some explanation about saving of current behavior.
Also, if directive #[repr(C)]
is not used:
-Z randomize-layout
flag. The flag is added by Kixiron, it randomizes the layout of structs.Upvotes: 2