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

时间:2012-04-25 03:47:02

标签: c++ memory-alignment

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

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

4 个答案:

答案 0 :(得分:7)

好问题。考虑这种假设类型:

struct A {
    int n;
    bool flag;
};

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

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

const size_t N = 100;
A a[N];

如果每个A只有五个字节,那么a[0]会对齐a[1]a[2],而大多数其他元素则不会。

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

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

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

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

答案 1 :(得分:1)

根据硬件的不同,可能需要对齐,或者只是帮助加快执行速度。

有一定数量的处理器(我相信ARM),其中未对齐访问会导致硬件异常。简单明了。

即使典型的x86处理器更宽松,但访问未对齐的基本类型仍然存在一些损失,因为处理器必须做更多的工作才能将这些位带入寄存器,然后才能对其进行操作。编译器通常在需要打包时提供特定的属性/编译指示。

答案 2 :(得分:0)

由于虚拟寻址。

  

“...在页面大小的边界上对齐页面可以让...   硬件通过替换将虚拟地址映射到物理地址   地址中的较高位,而不是复杂的算术。“

顺便说一下,我发现维基百科的页面写得非常好。

答案 3 :(得分:0)

如果CPU的寄存器大小为32位,则它可以使用单个汇编指令获取32位边界的存储器。获取32位的速度较慢,然后从第8位开始获取字节。

顺便说一句:没有填充。你可以要求打包结构。