C结构后增量增加4个字节的结构?为什么是这样?

时间:2012-05-24 14:22:05

标签: c

我有一个大小为48字节的结构,最近在其中添加了另一个大小为20字节的结构;所以结构的总大小变为68字节。 (所有成员都是无符号的int)

typedef struct{
           ...
           ...
           unsigned long long a1;
           struct s2
           }s1 ;

S1结构是一个数组;如果使用s1 ++增加s1,则观察到s1以72字节而不是68字节递增。令人惊讶的是,如果结构s2从s1中移除,则一切正常,即,s1以48字节递增。关于原因的任何指示都会有所帮助。

3 个答案:

答案 0 :(得分:3)

您没有说明您正在使用的编译器或平台,但很可能编译器正在添加对齐字节以使结构在8字节边界上对齐。这很常见。

答案 1 :(得分:1)

发生什么是结构填充。

由编译器完成,以确保元素驻留在对齐的内存地址。

您可以在x86 / x86_64 here中阅读有关'对齐'的更多信息。

现在,为什么他们应该在对齐的地址? (以4字节WORD为例):机器以“字”的形式从内存中访问数据。对于4字节的WORD,这意味着要从地址b11001110读取单个字节,您需要读取4个字节(地址中的最后2位基本上在读取时被忽略),然后选择WORD在CPU中时所需的字节:

| b11001100 | b11001101 | b11001110 | b11001111 |    <- all four loaded at once
                        \           /
                        only one used

当您开始阅读更大的数据类型时,读取“未对齐”数据的成本可能高于读取对齐的数据:

如果你想从地址b01110开始读取4个字节(1个WORD),而不是只读一个字节,那么你必须阅读2个字:

        first load             second load
/                       \/                      \
|01100|01101|01110|01111|10000|10001|10010|10011|
            \                       /
               unaligned data read

编译器'pad'结构以避免这种读取。因为它们很贵。正如Woodrow Douglass在their answer中建议的那样,你可以强制编译器“打包”而不是“打包”。

还有一件事:有些架构甚至无法实现未对齐的负载。在这样的机器上,操作系统通常捕获在未对齐的负载期间引发的异常,然后以某种方式模拟负载(例如,通过执行多个对齐的负载)。

答案 2 :(得分:-1)

这是64位机器吗? 72字节是64位字边界。您的编译器正在调整您的结构。在gcc中,如果使用__attribute__((__packed__))声明结构,则可以避免这种情况。

所以声明你的typedef是这样的:

typedef struct {
    ...
    ...
    struct s2;
} __attribute__((__packed__)) s1;