为什么struct的大小需要是任何struct成员的最大对齐的倍数

use*_*215 9 c++ memory-alignment

我理解结构成员之间发生的填充,以确保各个类型的正确对齐.但是,为什么数据结构必须是最大成员对齐的倍数?我不明白最后需要填充.

参考:http: //en.wikipedia.org/wiki/Data_structure_alignment

thb*_*thb 8

好问题.考虑这个假设类型:

struct A {
    int n;
    bool flag;
};
Run Code Online (Sandbox Code Playgroud)

因此,类型的对象A应该占用五个字节(四个用于int加一个用于bool),但实际上它需要八个字节.为什么?

如果你使用这样的类型,会看到答案:

const size_t N = 100;
A a[N];
Run Code Online (Sandbox Code Playgroud)

如果每个A只有五个字节,那么a[0]就会对齐但是a[1],a[2]大多数其他元素都不会.

但为什么对齐甚至重要?有几个原因,都与硬件有关.一个原因是最近/经常使用的内存缓存在CPU芯片上的缓存行中以便快速访问.小于高速缓存行的对齐对象总是适合单行(但请参见下面附加的有趣注释),但未对齐的对象可能跨越两行,浪费高速缓存.

实际上甚至有更基本的硬件原因,与字节可寻址数据沿着32位或64位数据总线传输的方式有关,与高速缓存线完全不同.不对称会导致总线堵塞额外的提取(由于之前的跨越),但它也会迫使寄存器在进入时移位字节.更糟糕的是,未对准往往会混淆优化逻辑(至少,英特尔的优化手册说虽然我对最后一点没有个人了解,但确实如此.因此,从性能角度来看,错位是非常糟糕的.

由于这些原因,浪费填充字节通常是值得的.

更新: 以下评论都很有用.我推荐他们.

  • @edA-qamort-ora-y:当然,但是作为基本类型复合的对象可能很容易跨越两条线。即使它更小。假设有 64 字节行,我可以有一个 48 字节大的对象,并且在此类对象的表中,至少有二分之一将跨越两个缓存行。 (2认同)
  • @MatthieuM.,是的,我只是想澄清原生类型.复合类型肯定会跨行,但它们的组成原生类型不会. (2认同)