【问题标题】:Memory alignment and size of structure内存对齐和结构大小
【发布时间】:2012-04-12 21:39:16
【问题描述】:

假设我定义了以下结构:

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

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

谢谢!

【问题讨论】:

  • 使用 sizeof() 进行一点谷歌搜索和测试可以为您提供大量信息。你可能会在这里找到一些有用的东西:c-faq.com

标签: c memory memory-management


【解决方案1】:

编译器可以根据需要填充结构。通常,最后两个bytes 不会被填充分隔,因此大小将变为4 (int) + 1 (char) + 3 (padding) + 4 (int) + 1 (byte) + 1 (byte) + 2 (padding) = 16

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

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

        #pragma pack(1)
        

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

        您可以通过打印 sizeof(struct MyData) 来轻松测试这一点

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-26
          • 2021-12-24
          • 2012-06-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多