背景
在 Rust 中,repr 是一個屬性(attribute),用于指定數據類型在內存中的布局和表現形式
repr 屬性可以用于枚舉、結構體和聯合體的定義,以控制它們的內部表示方式
repr 屬性有多個選項,每個選項對應于一種不同的布局方式
常見的選項包括:
- C
將類型按照 C 語言的規則進行布局和對齊。默認的 repr 屬性選項。 - transparent
將新類型(Newtype)與其內部類型具有相同的內存布局,沒有額外的內存開銷 - usize、u8、u16、u32、u64、u128
指定整數類型的具體大小和表示形式 - packed
無對齊的緊密壓縮布局,沒有填充字節 - align(n)
指定對齊方式為 n 字節對齊,其中 n 是 2 的次冪
#[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 的表示屬性可以更好地控制數據的內存布局和對齊方式
將新類型(Newtype)與其內部類型具有相同的內存布局?
希望定義一個新類型來提供更好的類型安全性/表示特定的語義,但又不想引入額外的內存開銷
通過使用 #[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) =