为什么不是sizeof等于每个成员的sizeof之和?

为什么'sizeof'运算符返回的结构体积比结构体的总尺寸要大?


这是因为添加了填充以满足对齐约束。 数据结构调整会影响程序的性能和正确性:

  • 错误对齐的访问可能是一个硬错误(通常是SIGBUS )。
  • 错误对齐访问可能是一个软错误。
  • 要么在硬件中纠正,要适度降低性能。
  • 或者通过软件仿真来纠正,以降低性能。
  • 另外,原子性和其他并发性保证可能会被破坏,从而导致微妙的错误。
  • 以下是使用x86处理器的典型设置(全部使用32位和64位模式)的示例:

    struct X
    {
        short s; /* 2 bytes */
                 /* 2 padding bytes */
        int   i; /* 4 bytes */
        char  c; /* 1 byte */
                 /* 3 padding bytes */
    };
    
    struct Y
    {
        int   i; /* 4 bytes */
        char  c; /* 1 byte */
                 /* 1 padding byte */
        short s; /* 2 bytes */
    };
    
    struct Z
    {
        int   i; /* 4 bytes */
        short s; /* 2 bytes */
        char  c; /* 1 byte */
                 /* 1 padding byte */
    };
    
    const int sizeX = sizeof(struct X); /* = 12 */
    const int sizeY = sizeof(struct Y); /* = 8 */
    const int sizeZ = sizeof(struct Z); /* = 8 */
    

    可以通过对齐排序成员(按照基本类型的大小进行排序)(如上面示例中的结构Z )来排列结构的大小,从而最小化结构的大小。

    重要提示:C和C ++标准都声明结构对齐是实现定义的。 因此,每个编译器可能会选择以不同方式对齐数据,从而导致不同的和不兼容的数据布局。 因此,在处理将由不同编译器使用的库时,理解编译器如何对齐数据很重要。 某些编译器具有命令行设置和/或特殊的#pragma语句来更改结构对齐设置。


    打包和字节对齐,如C常见问题中所述:

    这是为了对齐。 许多处理器无法访问2字节和4字节数量(例如,整数和长整数),如果它们在每一个方向都被塞住。

    假设你有这样的结构:

    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  |
    +-------+-------+-------+-------+
    

    如果你希望结构与GCC具有一定的大小,例如使用__attribute__((packed))

    在Windows上,使用带有/ Zp选项的cl.exe编译器时,可以将对齐方式设置为一个字节。

    通常,CPU可以更容易地访问4(或8)倍数的数据,这取决于平台以及编译器。

    所以这基本上是一个对齐的问题。

    你需要有充分的理由来改变它。

    链接地址: http://www.djcxy.com/p/12511.html

    上一篇: Why isn't sizeof for a struct equal to the sum of sizeof of each member?

    下一篇: What does int argc, char *argv[] mean?