为什么同样的字段,repr(C) 和默认布局大小不同?填充在哪里?怎么用声明顺序省空间?packed 为什么不能取引用?这篇用 offset_of 与字节转储直接把布局看出来。
编译:成功
运行(退出码 0):
repr(Rust): size 8 align 4 偏移 a=6 b=0 c=4
repr(C): size 12 align 4 偏移 a=0 b=4 c=8
字段本身合计 7 字节;repr(C) 多出的 5 字节是填充(padding)对齐与填充的更多细节见Struct 对齐与 Padding。repr(Rust) 的布局没有稳定保证,这里观察到的是 rustc 1.98.1 在 aarch64 上的结果。
编译:成功
运行(退出码 0):
repr(C) 声明顺序 u8,u64,u8,u32: 24 字节
repr(C) 声明顺序 u64,u32,u8,u8: 16 字节(按大小降序,填充最少)
repr(Rust) 同样四个字段(任意声明顺序): 16 字节(编译器自己重排) 编译:成功
运行(退出码 0):
packed: size 7 align 1(没有填充,各字段紧挨着)
align(16) 的 struct,只含一个 u32: size 16 align 16(大小被补到对齐的倍数)
按值读 packed 字段是安全的: b = 2
源码:
1 | #[repr(C, packed)] struct P { a: u8, b: u32 }
2 | fn main() { let p = P { a: 1, b: 2 }; let r = &p.b; println!("{}", r); }
编译:失败
error[E0793]: reference to field of packed struct is unaligned
--> <实验目录>/src/u112d.rs:2:47
|
2 | fn main() { let p = P { a: 1, b: 2 }; let r = &p.b; println!("{}", r); }
| ^^^^
|
= note: this struct is 1-byte aligned, but the type of this field may require higher alignment
= note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0793`. 编译:成功
运行(退出码 0):
默认 enum E0 {A,B,C}: 1 repr(u8): 1 repr(C): 4 repr(u32): 4
带数据 enum {A(u8), B(u32), C}: 默认 8 repr(C): 8
E1::C as u8 = 200(repr(u8) 的判别值可以读出来)枚举布局见Enum 的内存布局。
编译:成功
运行(退出码 0):
repr(C) 结构体的 12 个字节(十六进制): aa 00 00 00 44 33 22 11 ef be 00 00
tag 在字节 0,len 从字节 4 开始(小端:44 33 22 11),flags 从字节 8 开始(小端:ef be);其余是填充(内容未指定)