结构对齐填充,最大填充大小和结构成员的顺序

我一直在学习结构数据填充,因为我发现我的sizeof()运算符没有返回我的预期。 根据我观察到的模式,它将结构成员与最大的数据类型对齐。 所以例如……

struct MyStruct1 { char a; // 1 byte char b; // 1 byte char c; // 1 byte char d; // 1 byte char e; // 1 byte // Total 5 Bytes //Total size of struct = 5 (no padding) }; struct MyStruct2 { char a; // 1 byte char b; // 1 byte char c; // 1 byte char d; // 1 byte char e; // 1 byte short f; // 2 bytes // Total 7 Bytes //Total size of struct = 8 (1 byte of padding between char e and short f }; struct MyStruct3 { char a; // 1 byte char b; // 1 byte char c; // 1 byte char d; // 1 byte char e; // 1 byte int f; // 4 bytes // Total 9 bytes //Total size of struct = 12 (3 bytes of padding between char e and int f }; 

但是,如果将最后一个成员设为8字节数据类型(例如long long),它仍然只添加3个字节的填充,从而形成一个四字节对齐的结构。 但是,如果我构建在64位模式下,它实际上会对齐8个字节(最大的数据类型)。 我的第一个问题是,我说它使成员拥有最大的数据类型是错误的吗? 对于64位构建,此语句似乎是正确的,但在32位构建中仅适用于最多4字节数据类型。 这与CPU的原生“字”大小有关吗? 还是程序本身?

我的第二个问题是,以下是否会浪费整个空间和糟糕的编程?

 struct MyBadStruct { char a; // 1 byte unsigned int b; // 4 bytes UINT8 c; // 1 byte long d; // 4 bytes UCHAR e; // 1 byte char* f; // 4 bytes char g; // 1 byte // Total of 16 bytes //Total size of struct = 28 bytes (12 bytes of padding, wasted) }; 

谢谢。

如何填充,不是标准的一部分。 所以它可以在不同的系统和编译器上以不同的方式完成。 通常这样做是为了使变量在那里大小对齐,即大小= 1 – >没有对齐,大小= 2 – > 2字节对齐,大小= 4 – > 4字节对齐等等。 对于size = 8,通常对齐4或8个字节。 它自身的结构通常是4或8字节对齐。 但是 – 只是重复 – 它取决于系统/编译器。

在你的情况下,它似乎遵循上面的模式。

所以

 char a; int b; 

将3个字节填充给4个字节对齐int。

 char a1; int b1; char a2; int b2; char a3; int b3; char a4; int b4; 

将最终为32字节(再次为4字节对齐int)。

 int b1; int b2; int b3; int b4; char a1; char a2; char a3; char a4; 

因为int已经对齐,所以只有20。

所以如果记忆很重要,那就把最大的成员放在首位

但是,如果内存无关紧要(例如因为结构没有那么多使用),最好将事物保持在逻辑顺序中,以便代码易于为人类阅读。

以下所有内容均取决于实现。 不要依赖于程序的正确性(但无论如何都要利用它来调试或提高性能)。

通常,每种数据类型都有一个首选对齐方式。 这绝不会大于类型的大小,但可以更小。

看起来你的编译器在32位模式下编译时在32位边界上对齐64位整数,但在64位模式下在64位边界上。

关于MyBadStruct的问题:一般来说,编写简单易懂的代码; 如果你知道(通过测量)你有问题,只做其他事情。 话虽如此,如果按大小(最大的第一个)对成员变量进行排序,则可以最小化填充空间。

通常,减少编译器插入的填充量的最佳方法是将结构内部的数据成员从最大到最小排序:

 struct MyNotSOBadStruct { long d; // 4 bytes char* f; // 4 bytes unsigned int b; // 4 bytes char a; // 1 byte UINT8 c; // 1 byte UCHAR e; // 1 byte char g; // 1 byte // Total of 16 bytes }; 

大小可能会因32位与64位操作系统而异,因为指针的大小会发生变化

现场版: http : //coliru.stacked-crooked.com/a/aee33c64192f2fe0

我得到尺寸= 24