在 Rust 中,repr 是一个属性(attribute),用于指定数据类型在内存中的布局和表现形式
repr 属性可以用于枚举、结构体和联合体的定义,以控制它们的内部表示方式
repr 属性有多个选项,每个选项对应于一种不同的布局方式
常见的选项包括:
#[repr(C)]
struct MyStruct {
// 结构体字段
}
#[repr(transparent)]
struct Newtype(i32);
#[repr(packed)]
struct PackedStruct {
// 结构体字段
}
enum MyEnum {
Variant1,
#[repr(u8)]
Variant2(u8),
}
union MyUnion {
field1: u8,
field2: u32,
}
使用不同的 repr 属性选项,来指定不同类型的布局和表示形式
结构体 MyStruct 使用了默认的 C 表示方式
新类型 Newtype 使用了 transparent 表示方式
结构体 PackedStruct 使用了 packed 表示方式
枚举 MyEnum 的 Variant2 使用了 u8 表示方式
联合体 MyUnion 没有指定具体的 repr 属性
通过使用 repr 属性,可以控制数据类型在内存中的布局方式,
这对于与外部代码的交互、内存对齐、硬件访问等场景非常有用
需要谨慎使用 repr 属性,并根据具体的需求选择适当的选项
了解 Rust 的表示属性可以更好地控制数据的内存布局和对齐方式
希望定义一个新类型来提供更好的类型安全性/表示特定的语义,但又不想引入额外的内存开销
通过使用 #[repr(transparent)] 属性,确保新类型与其内部类型的内存布局完全相同
即没有任何额外的包装或填充字节
对于在代码中传递特定类型的参数、避免不必要的包装和解包以及与其它代码进行互操作性非常有用
#[repr(transparent)]
struct Newtype(i32);
Newtype 的新类型,内部包含了一个 i32 类型的字段
告诉编译器新类型 Newtype 的大小和对齐方式与 i32 完全相同
注意
#[repr(transparent)] 属性只适用于具有单个字段的新类型
且该字段的类型和新类型的类型必须是安全的(即无内部可变性和其他危险的属性)
对于不带标记的数据结构,默认 repr
repr 代表 rust 可以任意优化内存布局,对内部数据进行重排
保证其内部空间尽量紧凑,不包含过多的 padding
struct Rust {
#![feature(offset_of)]
use std::mem;
struct Rust {
a: u64,
b: bool,
c: u64,
d: bool,
}
fn main() {
dbg!(mem::size_of::<Rust>());
dbg!(mem::offset_of!(Rust, a));
dbg!(mem::offset_of!(Rust, b));
dbg!(mem::offset_of!(Rust, c));
dbg!(mem::offset_of!(Rust, d));
}
在不带 repr© 时,rust 会对其中的 field 进行重排
[src/main.rs:13] mem::size_of::<Rust>() = 24
[src/main.rs:14] mem::offset_of!(Rust, a) =