0

假设我定义了以下结构:

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 字节。

这是错的吗?我错过了什么吗?这是特定于语言的东西吗?我可以打包结构吗?如果是这样,有什么优点和缺点?

谢谢!

4

4 回答 4

2

您说内存对齐可以增加结构的大小并没有错;然而,任何关于如何对齐内存的猜测都不适用于所有平台。这是严格的平台特定的。

基本上,大多数平台倾向于在 ${WORDSIZE} 上对齐,或者如果数据类型小于 ${WORDSIZE},那么它会在 ${WORDSIZE} 的下一个可用部分上对齐

例如,如果您有一个 32 位字,并且您正在存储 16 位短路,它们可能会在一个字内的第 0 位和第 16 位上对齐。但这不是保证,因为它确实是特定于平台的。

要调整结构以减少因填充造成的浪费,请按数据类型对元素进行排序,首先使用较大的数据类型。这倾向于允许将多个字节打包到同一个单词中(如果可能的话),并且大于单词的项将很好地终止于单词边界,因为它们往往是单词的干净倍数(四字,双字,...)

于 2012-04-12T21:50:45.220 回答
2

编译器可以在它认为合适的时候填充结构。通常,最后两个bytes 不会被填充分隔,因此大小将变为4 (int) + 1 (char) + 3 (padding) + 4 (int) + 1 (byte) + 1 (byte) + 2 (padding) = 16.

许多编译器允许根据编译指示打包结构。这样做的好处是内存使用较少,缺点是非对齐int成员的读取速度较慢。

于 2012-04-12T21:43:25.553 回答
1

结构成员之间和之后有未指定的填充。第一个结构成员之前没有填充,即:

struct MyData bla;

int val = (char *) &bla == (char *) &bla.a;  // val is 1

指向结构的指针(经过适当转换)指向第一个结构成员。

结构对象的大小考虑了填充,等于成员大小的总和 + 未指定的填充大小的总和。

于 2012-04-12T21:42:03.730 回答
0

是的,编译器自然会在与其大小匹配的边界上对齐类型。您可以使用编译器编译指示强制结构打包,例如

#pragma pack(1)

您还可以通过重新排序声明以将整数放在开头和之后的单个字节来避免一些填充。

您可以通过打印轻松地对此进行测试sizeof(struct MyData)

于 2012-04-12T21:44:13.930 回答