【问题标题】:Why short is stored as 4 bytes in a struct in C?为什么 short 在 C 中的结构中存储为 4 个字节?
【发布时间】:2010-10-24 10:16:30
【问题描述】:

我有以下两个结构:

问题是 sizeof(Content) 返回 160。该结构由 11 个 short、6 个 int、76 个 chars、7 个 float、1 个 double 组成,总共增加了 158 个字节。我数了三遍,还是有2个字节的差别。

typedef struct TIME_T { 
    short year,mon,day; 
    short hour,min,sec; 
} TIME;

typedef struct { 
    int no; 
    char name[20]; 
    char Code[10]; 
    char DASType[10]; 
    short wlen; 
    float VLtd; 
    int samp; 
    int comp; 
    int locationID; 
    short TranMode; 
    char TranIns[12]; 
    short TimerMode; 
    char ClkType[12]; 
    float ClkErr; 
    float lat; 
    float lon; 
    float alt; 
    float azimuth,incident; 
    short weight; 
    short veloc; 
    int oritype; 
    char seismometer[12]; 
    double sens; 
    TIME start_time; 
    int record_samples; 
} Content;

我写了一小段代码来打印结构中每个变量的位置,突然我发现float wlen 需要4个字节。我的代码如下:

int main(void)
{   
    Content content;
    printf("Sizeof Content: %d\n", sizeof(content));
    printf("Sizeof int content.no: %d\n", (int)&content.name - (int)&content.no);
    printf("Sizeof char[20] content.name: %d\n", (int)&content.Code - (int)&content.name);
    printf("Sizeof char[10] content.Code: %d\n", (int)&content.DASType - (int)&content.Code);
    printf("Sizeof char[10] content.DASType: %d\n", (int)&content.wlen - (int)&content.DASType);
    printf("Sizeof short content.wlen:  %d\n", (int)&content.VLtd - (int)&content.wlen);
    printf("Sizeof float content.VLtdL %d\n", (int)&content.samp - (int)&content.VLtd);
    printf("Sizeof int content.samp: %d\n", (int)&content.comp - (int)&content.samp);
    printf("Sizeof int content.comp: %d\n", (int)&content.locationID - (int)&content.comp);
    printf("Sizeof int content.locationID: %d\n", (int)&content.TranMode - (int)&content.locationID);
    printf("Sizeof short content.TranMode: %d\n", (int)&content.TranIns - (int)&content.TranMode);
    printf("Sizeof char[12] content.TranIns: %d\n", (int)&content.TimerMode - (int)&content.TranIns);
    printf("Sizeof short content.TimerMode: %d\n", (int)&content.ClkType - (int)&content.TimerMode);
    printf("Sizeof char[12] content.ClkType: %d\n", (int)&content.ClkErr - (int)&content.ClkType);
    printf("Sizeof float content.ClkErr: %d\n", (int)&content.lat - (int)&content.ClkErr);
    printf("Sizeof float content.lat: %d\n", (int)&content.lon - (int)&content.lat);
    printf("Sizeof floatcontent.lon: %d\n", (int)&content.alt - (int)&content.lon);
    printf("Sizeof floatcontent.alt: %d\n", (int)&content.azimuth - (int)&content.alt);
    printf("Sizeof floatcontent.azimuth: %d\n", (int)&content.incident - (int)&content.azimuth);
    printf("Sizeof floatcontent.incident: %d\n", (int)&content.weight - (int)&content.incident);
    printf("Sizeof short content.weight: %d\n", (int)&content.veloc - (int)&content.weight);
    printf("Sizeof short content.veloc: %d\n", (int)&content.oritype - (int)&content.veloc);
    printf("Sizeof int content.oritype: %d\n", (int)&content.seismometer - (int)&content.oritype);
    printf("Sizeof char[12] content.seismometer: %d\n", (int)&content.sens - (int)&content.seismometer);
    printf("Sizeof double content.sens: %d\n", (int)&content.start_time - (int)&content.sens);
    printf("Sizeof TIME content.start_time: %d\n", (int)&content.record_samples - (int)&content.start_time);
    printf("Sizeof int content.record_samples: %d\n", sizeof(content.record_samples));

    getchar();
    return 0;
}

输出如下:

Sizeof int content.no: 4
Sizeof char[20] content.name: 20
Sizeof char[10] content.Code: 10
Sizeof char[10] content.DASType: 10
Sizeof short content.wlen:  4
**Sizeof float content.VLtdL 4**
Sizeof int content.samp: 4
Sizeof int content.comp: 4
Sizeof int content.locationID: 4
Sizeof short content.TranMode: 2
Sizeof char[12] content.TranIns: 12
Sizeof short content.TimerMode: 2
Sizeof char[12] content.ClkType: 12
Sizeof float content.ClkErr: 4
Sizeof float content.lat: 4
Sizeof floatcontent.lon: 4
Sizeof floatcontent.alt: 4
Sizeof floatcontent.azimuth: 4
Sizeof floatcontent.incident: 4
Sizeof short content.weight: 2
Sizeof short content.veloc: 2
Sizeof int content.oritype: 4
Sizeof char[12] content.seismometer: 12
Sizeof double content.sens: 8
Sizeof TIME content.start_time: 12
Sizeof int content.record_samples: 4

编译器为 MSVC8,未定义 UNICODE,未定义其他宏。它是 x86。

我尝试在 gcc 版本 3.4.4 中编译相同的代码,输出是相同的。 Sizeof short content.wlen: 4

谁能给我解释一下?

提前致谢。

编辑:感谢您的回答!我已经拿到了。

【问题讨论】:

  • 请参见此处:stackoverflow.com/questions/713963/why-does-this-c-code-work,了解计算数据成员偏移量的宏。这是一个不同的讨论,但那里的宏可以工作......
  • 您不应使用 %d 打印 sizeof 返回的尺寸。类型 si size_t,一般是 unsigned int 或 unsigned long 的 typedef。它依赖于平台,因此您必须先转换它,然后才能使用特定于类型的格式:"%u", (unsigned int)sizeof(...) 或 "%lu\n", (unsigned long)sizeof( ...)。我相信 C99 添加了 size_t 格式,这让事情变得更简单。

标签: c struct sizeof


【解决方案1】:

对齐——在 32 位架构上,以 32 位块的形式传递内存要高效得多。通过以 16 位存储 short 实际上根本不会节省任何内存,因为它仍然是关联的 32 位字的一部分。

【讨论】:

  • 但通常结构中的两个相邻的short 将被打包在一起,因为通常的规则是使用填充将每个成员置于其“自然”对齐。当然,整个问题是实现定义的行为,所以你的里程会有很大的不同。
【解决方案2】:

正如 dfa 所说,这是由于对齐。一种有助于减小结构大小的“良好做法”是从最大的成员开始,按成员的个人大小(实际上是他们各自的对齐方式,但大小通常足够好)对其成员进行排序。

这并不总是正确的,但大多数时候都是这样。

【讨论】:

    【解决方案3】:

    看看pahole,Poke-a-Hole 的缩写。它是 DWARF2 工具之一,用于查找结构中的孔,由于对齐规则,孔是成员之间的空间,可用于新的结构条目或重新组织以减小大小。

    在this LWN article 中阅读程序作者 Arnaldo Carvalho de Melo 的更多信息。

    网上的教程不多,但this wiki-page at CERN有点用处。

    【讨论】:

      【解决方案4】:

      根据 C 标准,内存中的每个本机类型都必须与其大小对齐,但与您的问题没有直接关系。您应该研究的是结构打包。

      【讨论】:

        【解决方案5】:

        如果编译器发现这样访问会更方便,结构成员通常会在 4 字节边界上对齐。 char 也会发生类似的行为。

        您可以尝试通过将 short 放在一起来优化结构的内存占用,以便两个连续的 short 使用单个 32 位字。不要忘记仔细检查编译器结果。

        【讨论】:

          【解决方案6】:

          在结构中添加另一个short 是否会扩大尺寸,还是保持不变?我敢打赌,它的大小保持不变。

          两个编译器都在努力使你的结构保持 8 字节对齐(我猜想),因此某些字段将被“扩展”以占用额外的空间;对该字段的实际操作将表现得好像它是“适当的”大小。

          【讨论】:

          • 当且仅当在 wlen 成员附近插入新的 short 以便可以重新使用现有的填充字节时,它可能会保持相同的大小。将它插入到几乎任何其他位置都可能会导致另外两个填充字节发生。
          【解决方案7】:

          您不是在计算字段的大小,而是在计算它们之间的“距离”,所以我猜您看到的是结构内的字对齐。

          【讨论】:

            【解决方案8】:

            您不能简单地通过添加其所有组件的大小来计算结构的大小 - 允许编译器在字段之间插入填充,并且经常这样做。

            【讨论】:

              【解决方案9】:

              仅简短回答:alignment

              【讨论】:

                猜你喜欢
                • 2022-07-12
                • 1970-01-01
                • 1970-01-01
                • 2011-08-10
                • 1970-01-01
                • 2020-03-21
                • 2021-05-27
                • 2017-06-08
                • 2014-11-30
                相关资源
                最近更新 更多