假设我定义了以下结构:
struct MyData {
int a;
char b;
int c;
byte d;
byte e;
}
我依稀记得读到该结构的大小不仅取决于数据类型,还取决于内存对齐。在32位CPU上,MyData结构将是4个字节+ 1个字节+4个字节+ 1个字节+ 1个字节= 11个字节。这是我的问题,是内存对齐增加了结构的大小:4字节+ 1字节(+3字节填充)+ 4字节+ 1字节(+3字节填充)+ 1字节(+3字节填充)= 20字节。
这是错的吗?我错过了什么吗?这是特定于语言的吗?我可以打包结构吗?如果是这样,有什么优点和缺点?
谢谢!
答案 0 :(得分:2)
编译器可以根据需要填充结构。通常情况下,最后两个byte
不会被填充分隔,因此大小将变为4 (int) + 1 (char) + 3 (padding) + 4 (int) + 1 (byte) + 1 (byte) + 2 (padding) = 16
。
许多编译器允许按照编译指示打包结构。这样做的好处是内存使用量减少,对于未对齐的int
成员,读取速度较慢。
答案 1 :(得分:2)
说明内存对齐可以增加结构的大小并没有错;但是,任何关于内存如何对齐的猜测都不适用于所有平台。这是严格的平台特定。
基本上,大多数平台倾向于在$ {WORDSIZE}上对齐,或者如果数据类型小于$ {WORDSIZE},那么它在$ {WORDSIZE}的下一个可用分数上对齐
例如,如果您有一个32位字,并且存储了16位短路,则它们可能在一个字内的第0位和第16位对齐。但这不是保证,因为它确实是特定于平台的。
要根据填充调整结构以减少浪费,请按数据类型对元素进行排序,首先使用较大的数据类型。这往往允许多个字节被打包到同一个单词中(如果可能的话)并且大于单词项将很好地终止于单词边界,因为它们往往是单词的清晰倍数(四字,双字,...)
答案 2 :(得分:1)
在struct成员之间和之后有未指定的填充。在第一个struct成员之前没有填充,即:
struct MyData bla;
int val = (char *) &bla == (char *) &bla.a; // val is 1
指向结构的指针(适当转换)指向第一个结构成员。
结构对象的大小考虑了填充,并且等于成员大小的总和+未指定填充的大小的总和。
答案 3 :(得分:0)
是的,编译器会自然地在与其大小匹配的边界上对齐类型。您可以使用编译器编译指示强制进行结构打包,例如
#pragma pack(1)
你也可以通过重新排序声明来避免一些填充,将你的整数放在开头,然后单个字节。
您可以通过打印sizeof(struct MyData)