Rust编译器不会保证类型的布局,但是提供了一个属性用来对类型添加布局要求,如下所示:
#[repr(C)]
struct Foo {
tiny: bool,
normal: u32,
small: u8,
long: u64,
short: u16,
}
#[repr(C)]
提供了兼容C/C++编译器的类型布局,当你在使用FFI的时候会很有帮助,关于FFI我们后续再提。#[repr(C)]
会让结构的对齐顺序和代码的编写顺序一致。
下面是对上述struct
的布局的详细解释:
field | 占用字节数 | padding字节数 | 到目前为止占用的字节数 |
---|---|---|---|
tiny |
1 | 3 | 4 |
normal |
4 | 0 | 8 |
small |
1 | 7 | 16 |
long |
8 | 0 | 24 |
short |
2 | 6 | 32 |
-
tiny
需要对其的原因是后面的normal
占用4个字节,为了对齐需要添加3个字节。 -
small
为了和后面的long
对齐要添加8个字节才行。 - 整个
Foo
结构也需要对齐并且整个结构中最大的对齐字段是long
是8个字节,所以Foo
最后要对short
进行8个字节的对齐。
其他布局
repr(Rust)
Rust中布局方式和编写方式没有多大的关系,在上述的例子中正好可以将其放在16个字节中。
repr(packed)
这种布局方式不会添加padding,适用于内存特别紧张的情况,但是一般不建议,因为有些CPU可能并不支持这种没有对齐的数据。
repr(align(n))
指定特定的对齐数,主要用指定比默认的对齐要大的情况。这样做的一个好处是在一段连续的内存(例如数组)中存储的不同的值位于不同的缓存CPU行,能避免掉False Sharing的问题。