C++ 结构体对齐,是按照结构体成员中最大对齐要求进行对齐还是按照结构体大小进行对齐?

4

以这个结构为例:

struct Packing
{
     int x; // 4-byte align
     int y; // 4-byte align
     short int z; // 2-byte align
     char m; // 1-byte align;
     char _pad[1]; // explicit padding
};

这个结构体的大小是12字节。

那么应该将这个结构体存储在结构体大小(12字节)的地址倍数上,还是存储在sizeof(int)的倍数上(结构体成员中最大的对齐要求)?

由于12的倍数也是4(sizeof(int))的倍数,我猜结构体在12的倍数地址上会正确对齐,但如果它是4字节对齐的话,可能会浪费一些空间。

编辑:在地址0x00000012处,该结构体将被对齐,并且它的第一个成员也将被对齐,因为12是4的倍数。 如果将其存储在地址0x00000004处,情况会怎样呢?在这种情况下,结构体的第一个元素将被对齐,但结构体本身会如何对齐呢?


你是否正在尝试编写可在多个编译器上运行的可移植代码? - Alok Save
1
应该存储这个函数,存储什么? - Mu Qiao
__pad 是一个反向标识符。 - R. Martinho Fernandes
5
它也是一个保留标识符。 - Paul R
哦,该死 :) 是的,就像Paul说的那样。 - R. Martinho Fernandes
显示剩余2条评论
3个回答

5
如果你想在任何Intel CPU上实现最佳性能,你应该遵循Intel优化手册中的以下准则:
• 将8位数据对齐到任何地址。
• 将16位数据对齐,使其包含在对齐的4字节单词内。
• 将32位数据对齐,以使其基地址为4的倍数。
• 将64位数据对齐,以使其基地址为8的倍数。
• 将80位数据对齐,以使其基地址为16的倍数。
• 将128位数据对齐,以使其基地址为16的倍数。
因此,在您的情况下,您应该按16对齐,而不是4或8,因为您的结构体长度介于64位和128位之间,16是最佳上限,它还可以启用其他额外的功能,如能够使用SIMD复制结构体。

@David:不,那是用于访问结构体成员的。 - Necrolis
@David:你真绅士,谢谢 :) 如果事情能够变得简单就好了 :P - Necrolis
16字节对齐一路走来。SIMD不仅用于移动/复制,还可用于清零新分配的数组。 - Louis Ricci
那我应该将结构体对齐到最接近的2的幂次方吗?例如:60字节的结构体 -> 64字节对齐? - Tiago Costa
@Tiago:对于小于49的尺寸,不是2的幂次方,而是16的倍数,否则为64,但这取决于您如何使用内存和您的约束条件,最好自己阅读英特尔优化手册,以便更好地理解。此外,应注意,如果结构具有“奇怪”的成员,则可以重新排列结构以更改其对齐需求。 - Necrolis
显示剩余8条评论

4

结构体的最佳对齐方式等于结构体成员中的最大对齐方式。在这种情况下,最大对齐方式为4。

更新

以上假设你主要操作结构体的是访问其成员。请参考Necrolis的回答的评论以获取更多讨论。简而言之,我怀疑你的问题的真正答案很大程度上取决于所涉及的硬件和使用的算法。


对齐结构元素可优化访问速度。打包结构元素可优化大小。 - Steve Wellens
3
正确对齐结构可以优化避免未定义行为,在你最不希望的时候悄悄破坏你的代码。 - jalf
@downvoter,与其无声地给我点踩,请告诉我哪里有问题。这样我就可以修正或者删除它了。我可不想被错误陈述牵连,所以如果你指出我的错误,我不会生气。 - David Heffernan
所以,为了明确起见:如果主要目标是访问结构的成员,则结构的最佳对齐方式等于结构中任何成员的最大对齐方式。另一方面,如果主要目标是复制结构(或其他使用整个结构的操作),则像“Necrolis”一样对齐它可以提供更好的性能,对吧? - Tiago Costa
1
@tiago 我认为你的说法在一般情况下可能是正确的,尽管我相信你可以找到某些平台上某些操作的例外情况! - David Heffernan
显示剩余3条评论

0
编译器可以留下任何间隔以确保能够高效地访问结构。所需的精确对齐方式取决于底层架构。如果您使用的是32位架构且没有半字或字节数据加载,编译器可能会将所有数据成员(包括z、m和_pad)都对齐到字边界。但是,如果架构可以进行有效的半字和字节数据加载,则您可能会发现您的结构体具有预期的sizeof(Packing) == 12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接