结论:repr(Rust) 是默认布局,编译器有权重排字段顺序、调整对齐以优化空间(把大对齐字段排前面减小填充),且不保证跨版本一致;需要稳定布局时必须显式标注:repr(C) 与 C 兼容(字段按声明顺序、C 的对齐填充规则),repr(transparent) 单字段零开销包装,repr(u8/u16/...) 给枚举指定判别值类型,repr(packed) 取消对齐填充,repr(align(N)) 提高对齐。

展开:默认重排带来的实际影响:相同字段不同声明顺序的两个结构体可能大小不同(编译器统一优化);不能把 Rust 结构体的内存直接 transmute 或与 C 互操作——布局是实现细节。FFI 场景一律 repr(C);newtype 想做 transmute 或数组化转换用 repr(transparent)(保证与唯一非零大小字段同布局);解析二进制协议用 repr(C, packed) 但注意 packed 下取字段引用会未对齐,是 UB 温床,应逐字段拷贝读取。易错点:repr(C) 的枚举布局是"标签 + 最大变体的联合体",与 C 的 enum 仍不同,跨 FFI 传 Rust enum 要小心。

#[repr(C)]
struct Header { magic: u32, len: u16 }  // 布局固定,可写给 C

#[repr(transparent)]
struct UserId(u64);                     // 与 u64 同布局

追问方向:字段重排的优化收益、#[repr(C)] union 的用途、zerocopy/bytemuck 如何安全地字节化。