关于C#:在不同的编译器上使用显式宽度成员对齐struct

Alignment of struct with explicit width members on different compilers

我想知道,如果手动填充结构,使每个成员在其大小的地址倍数处对齐,并且所有对象都具有已知的显式宽度,那么二进制布局到底会是"预期的"/预期的布局,我能期望达到什么程度?也许有一些特定于编译器的选项来确保布局与声明的完全一致?

IIRC的C标准不允许任何重新排序,所以只有最终的额外填充是有问题的。如果按照自己的对齐规则填充结构,编译器是否需要添加填充?


默认情况下,编译器将与32或64位对齐。是的,有一些特定于编译器的选项可以将对齐设置为自定义值。

因此,如果要控制结构字段的对齐,可以使用编译器标志或pragma来实现。

如果是GCC,那就是-fpack-struct=[n]

在源代码中,可以用#pagma pack#pagma push(pack)包围结构的定义:

1
2
3
#pragma pack(push(n))
typedef struct my_struct {...} my_struct_t;
#pragma pack(pop)

GCC文件:http://gcc.gnu.org/onlinedocs/gcc/structure-packing-pragma.html

MSDN文档:http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx


(我可能错了,但是)我不知道标准中有什么要求填充最小的。考虑到这一点,编译器似乎有权在成员之间和结构末尾(但不是在开始处)放置任意数量的填充,即使不需要填充来满足对齐要求。因此,手动填充到32或64位并不能保证防止编译器添加填充,即使它可能适用于所有实际编译器。

正如其他人所指出的,有一些特定于编译器(即非标准)的方法可以强制结构完全没有编译器提供的填充,但不用于控制填充。

即使您可以精确地指定填充,您仍然没有精确地定义结构内容,因为您没有定义成员的表示(例如,big-endian或little-endian整数),所以我不确定您从中获得了什么,特别是在需要可移植性的情况下。您已经精确地定义了成员的偏移,但没有定义它们的表示。


您可以在代码中指定强制填充,例如:__attribute__((aligned (16)));。我认为还有另一个属性名packed来指定您不希望编译器对齐您的结构。有关详细信息,请参阅此链接