结构体的大小如何正确计算?

12 浏览
0 Comments

结构体的大小如何正确计算?

在Windows 7 64位系统上,MyStruct的大小是多少?

    typedef struct MyStruct_tag
   {
       char        c;
       double      d;
       int         s;
    } MyStruct;

我的回答是:

1(Char)+ 7(填充)+ 8(double)+ 4(int)= 20字节

但实际答案是24字节。发生了什么事?

0
0 Comments

结构体大小的计算正确是因为“对齐”。许多处理器如果2字节和4字节的数量(例如int和long int)被压缩在任何位置,就无法访问它们。

假设你有这样一个结构体:

struct  {
    char a[3];
    short int b;
    long int c;
    char d[3];
    };

现在,你可能认为它应该可以将这个结构体像这样压缩到内存中:

+-------+-------+-------+-------+

| a | b |

+-------+-------+-------+-------+

| b | c |

+-------+-------+-------+-------+

| c | d |

+-------+-------+-------+-------+

但是对于处理器来说,如果编译器按照这样的方式排列它,就要困难得多。

+-------+-------+-------+

| a |

+-------+-------+-------+

| b |

+-------+-------+-------+-------+

| c |

+-------+-------+-------+-------+

| d |

+-------+-------+-------+

在“压缩”版本中,请注意b和c字段如何包装?简而言之,对处理器来说,这也很困难。因此,大多数编译器会像这样“填充”结构体(好像有额外的不可见字段):

+-------+-------+-------+-------+
|           a           | pad1  |
+-------+-------+-------+-------+
|       b       |     pad2      |
+-------+-------+-------+-------+
|               c               |
+-------+-------+-------+-------+
|           d           | pad3  |
+-------+-------+-------+-------+

在上述映射中,你是否假设int为2字节?

这个问题的原因是很多处理器需要对齐数据,以提高访问效率。解决方法是通过在结构体中添加填充字段来对齐数据,以确保结构体的大小计算正确。

0
0 Comments

问题的出现的原因是结构体中的最后一个int类型的变量后面可能会有4个字节的填充,以保证数组中下一个相似结构体中的double类型变量的对齐方式正确。但是,填充字节的具体大小是由编译器实现定义的,尝试推理或预测它没有意义。编译器应该为你处理好这个问题。如果没有处理好,强烈建议重新考虑你的做法。

解决方法是使用__attribute__((packed))来指定结构体的属性不需要对齐(不是最佳实践)。

0