内存对齐和结构大小

时间:2012-04-12 21:39:16

标签: c memory memory-management

假设我定义了以下结构:

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 个答案:

答案 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)

轻松测试