Rust编程知识拾遗:内存布局
2020-03-24 本文已影响0人
令狐壹冲
1、每种类型都有一个数据对齐属性。在X86平台上u64和f64都是按照32位对齐的。
2、一种类型的大小是它对齐属性的整数倍,这保证了这种类型的值在数组中的偏移量都是其类型尺寸的整数倍,可以按照偏移量进行索引。需要注意的是,动态尺寸类型的大小和对齐可能无法静态获取。
3、结构体的对齐属性等于它所有成员的对齐属性中最大的那个。Rust会在必要的位置填充空白数据,以保证每一个成员都正确地对齐,同时整个类型的尺寸是对齐属性的整数倍。
例子:
struct A {
a: u8,
b: u32,
c:u16,
}
会填充为:
struct A {
a: u8,
_pad1: [u8; 3], // 为了对齐b
b: u32,
c: u16,
_pad2: [u8; 2], // 保证整体类型尺寸是4的倍数
}
4、注意点,两个同样类型的复合类型其分布规则并不一定一尘不变。例子:
struct A {
a: i32,
b: u64,
}
struct B {
a: i32,
b: u64,
}
Rust中不保证A的实例和B的实例有同样的数据填充和成员顺序。
原因:Rust编译器会进行优化。如下:
struct Foo<T, U> {
count: u16,
data1: T,
data2: U,
}
对于上面的泛型结构体,Foo<u32, u16>和Foo<u16, u32>按照内存优化的原则要求两者顺序不一样。
5、求解结构体的大小
使用std::mem,有两种方法,分布是size_of_val和size_of,例子如下:
use std::mem;
struct A {
a: u8,
b: u16,
}
fn main() {
let aa = A {a: 1, b:2};
println!("size = {}", mem::size_of_val(&aa));
println!("size = {}", mem::size_of::<A>());
println!("Hello, world!");
}