本页目录
基础类型与内存布局
Rust 的每个类型都有精确的内存布局——整数和浮点按位宽对齐,struct 有 padding,零大小类型(ZST)占 0 字节,niche optimization 让
Option<bool>和bool一样大(因为 bool 只有 0/1,编译器用 2 的位模式表示 None)。理解布局是理解为什么 Rust 没有"装箱开销"的前提。
标量类型: 不仅是"和 C 差不多"
Rust 的整数类型和 C 看起来一样——i32, u64 等等——但语义上有重要区别:
let x: u8 = 255;
// x + 1: debug mode → panic!("attempt to add with overflow")
// release mode → wraps to 0 (two's complement, 无未定义行为)
// 三种显式溢出处理:
255u8.checked_add // None (返回 Option, 不 panic)
255u8.wrapping_add // 0 (明确要 wrap)
255u8.saturating_add // 255 (饱和运算)
C 中 signed integer overflow 是 UB。Rust 中即使 release mode 的 wrap 也是定义好的行为——不是 UB。但 debug mode 的 panic 让你在测试中暴露溢出 bug。
类型大小和对齐
每种类型有确定的 size_of 和 align_of,不依赖平台(除了 isize/usize):
use ;
// 1
// 8
// 1 (不是 1 bit! 内存最小寻址单位是 byte)
// 4 (Unicode scalar value, 不是 code point)
// 0 (unit type, ZST)
// 8 (64-bit) or 4 (32-bit)
bool 占 1 byte 的原因:CPU 指令集寻址的最小单位是 byte。Rust 不允许取 bool 的某一位的地址。如果需要紧凑存储 bool 数组,用 bitvec crate 或 Vec<u64> 手动 bit-packing。
char: 4 bytes = 一个 Unicode scalar value
let c: char = 'あ'; // U+3042, 3 bytes in UTF-8, 4 bytes as char
// 4
// char 和 string 的关系:
let s = "あ"; // &str, 3 bytes: [E3, 81, 82]
let c = 'あ'; // char, 4 bytes: 0x00003042
char 代表一个 Unicode scalar value(0x0000~0xD7FF, 0xE000~0x10FFFF),不是"一个字符"(user-perceived character 可能是多个 scalar values 组合,如 é = e + ́)。这与 Go 的 rune(=int32)类似。
复合类型的内存布局
// memory: [a:1B][padding:3B][b:4B][c:2B][padding:2B] = 12 bytes
// C ABI: 字段按声明顺序, 自动 padding 满足对齐要求
// 默认 layout: 编译器可以重排字段以优化大小!
// 可能排列为: [b:4B][c:2B][a:1B][padding:1B] = 8 bytes
默认 Rust layout 不保证顺序——编译器可以 reorder 字段来减小 padding。如果需要与 C 互操作或保证稳定布局,必须 #[repr(C)]。
数组: 大小是类型的一部分
let arr1: = ; // 编译期固定大小
let arr2: = ; // 栈上 4000 bytes!
// 按值传递: 拷贝整个 4000 bytes
// 引用传递: 只拷贝 fat pointer (16 bytes)
数组按值传递会复制整个数组——因为 Rust 的 move semantics 对数组是逐元素复制。对于大数组,总是传 &[T] 或 &[T; N]。
ZST (Zero-Sized Types): 编译时隐形的魔法
; // 0 bytes
let x = NoData; // 不占任何栈空间
let arr: ; // 0 bytes! 没有分配任何内存
// ZST 的实用价值: HashMap 的 key
use HashSet;
let set: = ...; // 只区分"存在"和"不存在"
编译器在生成代码时完全省略 ZST 的存储和传递——它们不存在于运行时的任何地方,只有类型层面的意义。
Niche Optimization: 零成本的 Option
Rust 编译器利用"不可能的比特模式"来节省 enum 的空间:
// 1 byte, not 2!
// bool 只有 0x00 (false) 和 0x01 (true) 两个有效值
// 编译器用 0x02 表示 None → 不需要额外的 discriminant field
// 8 bytes, not 16!
// &T 保证 non-null → 编译器用 nullptr 编码 None
// 解引用 Option<&T> 时: 先检查是否为 null → None → panic/return None
// → Some 则就是正常引用
// 8 bytes — Box 内部是 non-null ptr
// 8 bytes — 两个 niche: nullptr 和 ...?
// 实际上 Option<&T> 只有一个 niche (null)
// Option<Option<&T>> 需要 2 niche values → 16 bytes (two words)
这个优化是 Rust 能在系统级安全中保持零开销的关键——你不需要为 Option<&T> 付出额外的内存或运行时代价。
参考
- Rust Reference: Type Layout (section "Data Layout")
- Rustonomicon: Exotic Sizes, repr, alignment
- RFC: RFC 139 (niche optimization)
Keywords: integer types, alignment, repr(C), ZST, niche optimization, Option<&T>, layout, size_of, align_of