【问题标题】:How does sizeof calculate the size of structuressizeof如何计算结构的大小
【发布时间】:2011-02-09 05:21:38
【问题描述】:

我知道由于对齐,char 和 int 在 32 位架构上被计算为 8 个字节,但我最近遇到了一种情况,即 sizeof 运算符将具有 3 个短裤的结构报告为 6 个字节。代码如下:

#include <iostream>
using namespace std ;

struct IntAndChar
{
    int a ;
    unsigned char b ;
};


struct ThreeShorts
{
    unsigned short a ;
    unsigned short b ;
    unsigned short c ;
};


int main()
{
    cout<<sizeof(IntAndChar)<<endl; // outputs '8'
    cout<<sizeof(ThreeShorts)<<endl; // outputs '6', I expected this to be '8'
    return 0 ;
}

编译器:g++ (Debian 4.3.2-1.1) 4.3.2。这真的让我很困惑,为什么包含 3 个短裤的结构不强制对齐?

【问题讨论】:

    标签: c++ alignment sizeof


    【解决方案1】:

    我不知道您从哪里得知charint 被计算为“8 个字节”。不,每种类型都根据其大小计算:char 为 1,int 在 32 位平台上为 4(不是 8,而是 4)。每种类型的对齐要求通常与其大小相同(尽管并非必须如此)。

    因此,当结构包含 相同 类型的成员时,该结构的总大小通常是其成员大小的精确总和:结构为 3 @987654325 @s 大小为 3,两个 ints 的结构大小为 8。

    显然,在您的平台上键入 short 的尺寸为 2,因此,预计 3 条短裤的结构尺寸为 6,这正是您所观察到的。

    但是,当您的结构包含不同类型的成员时,不同类型的对齐要求之间的差异就会发挥作用。如果下一个字段的对齐要求比前一个字段的对齐要求更严格,编译器可能必须在这些字段之间添加一些填充字节(以正确对齐下一个成员),这将影响结构的最终大小。此外,编译器可能必须在结构的最后一个成员之后添加一些额外的填充字节以满足数组中的对齐要求。

    例如,如下所示的结构

    struct S {
      char c;
      int i;
    };
    

    在您的平台上很可能会占用 8 个字节,因为在 char 成员之后需要 3 个填充字节。请注意,char 计为 1,int 计为 4,它们之间的额外 3 个填充字节使其为 8。

    还请注意,这可能很容易引入结构的最终大小对声明成员的顺序的依赖性。比如这个结构

    struct S1 {
      char c1;
      int i;
      char c2;
    };
    

    在您的平台上可能有 12 码,而这个

    struct S2 {
      int i;
      char c1;
      char c2;
    };
    

    将只占用 8 个字节。最后一个示例旨在说明结构的最终大小不能用每个成员“计数”多少字节来表示。成员之间的关系也很重要。

    【讨论】:

      【解决方案2】:

      是的,我遇到了同样的问题。我有以下结构

      struct Node{
          short digit;
          Node* next;
      };
          cout<<":"<<sizeof(Node)<<":"<<sizeof(short)<<":"<<sizeof(Node*)<<endl;
      

      这给了我 ::8:2:4 ??为什么结构的总和 = 8,但单个元素不加总? 这是因为内存对齐,内存填充了额外的 2 个字节用于对齐。 谢谢

      【讨论】:

        【解决方案3】:

        这真的让我很困惑,为什么不对 t 强制对齐

        你希望它有什么对齐方式?

        Shorts 可以在 2 字节边界上对齐而不会产生不良影响(假设这里到处都是常见的 x86 编译器..)。因此,如果您创建一个 struct ThreeeShorts 数组,则该结构的大小为 6 即可,因为此类数组中的任何元素都将从 2 字节边界开始。

        您的 struct IntAndChar 包含一个 int,ints 需要 4 字节对齐,因此如果您创建一个 struct IntAndChar 数组,则大小必须为 8 才能使下一个元素在 4 字节边界上对齐。

        如果我们不考虑数组,那么struct IntAndChar 的长度为 5 个字节也没关系,当您在堆栈中创建一个或将其用作另一个结构中的复合成员。

        你总是可以通过sizeof(arrayofT)/sizeof(T)得到一个数组的元素个数,并且保证数组元素是相邻存储的,这样第n个元素就可以通过步进N*来获取sizeof(arrayelementtype) 字节,这就是你会看到结构在最后被填充的主要原因。

        【讨论】:

        • 并不是我想要任何特定的对齐方式,只是我认为 32 位架构始终遵循 4 字节对齐方式
        • 只要!这肯定会使编写内存分配器变得更加容易......不幸的是,对齐方式可能因一种类型而异,并且没有可移植的方式来询问编译器关于给定类型的特定对齐方式,尽管有技巧。跨度>
        • #define alignof(type) ((char *)&amp;((struct { char dummy; type x; } *)0)-&gt;x - (char *)0)
        【解决方案4】:

        这是因为int 是 4 个字节,并且必须与 4 个字节的边界对齐。这意味着任何包含intstruct 也必须与至少4 字节对齐。

        另一方面,short 是 2 个字节,只需要与 2 个字节的边界对齐。如果包含shorts 的struct 不包含任何需要更大对齐的内容,则struct 也将对齐为2 字节。

        【讨论】:

          【解决方案5】:

          它完全依赖于实现,但如果您的系统可以访问结构中的三个short中的任何一个而不担心对齐,它可以访问任何short,因此可以访问数组中的任何数据成员的ThreeShorts 无需担心对齐。因此不需要更严格地对齐结构。

          对于IntAndChar 示例,int 的大小大概为 4,而实现 关注其对齐方式。为确保IntAndChar 数组中的每个int 成员都正确对齐,必须填充结构。

          sizeof 数组 T[n] 完全定义为 sizeof(T) * n

          【讨论】:

            【解决方案6】:

            此链接应该会有所帮助:http://en.wikipedia.org/wiki/Data_structure_alignment

            ThreeShorts 中的所有成员都是两个字节对齐的。

            【讨论】:

              猜你喜欢
              • 2019-05-08
              • 2015-06-03
              • 1970-01-01
              • 2014-10-04
              • 1970-01-01
              • 2021-05-06
              • 1970-01-01
              • 1970-01-01
              • 2013-05-30
              相关资源
              最近更新 更多