为什么short在C的结构中存储为4个字节?

为什么short在C的结构中存储为4个字节?,c,struct,sizeof,C,Struct,Sizeof,我有以下两个结构: 问题是sizeof(Content)返回160。该结构由11个短字符、6个整数、76个字符、7个浮点、1个双精度组成,总共增加到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]

我有以下两个结构:

问题是sizeof(Content)返回160。该结构由11个短字符、6个整数、76个字符、7个浮点、1个双精度组成,总共增加到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
结果如下:

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

谁能给我解释一下吗

提前谢谢


编辑:谢谢您的回答!我现在知道了。

仅简短回答:

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

您没有计算字段的大小,而是计算字段之间的“距离”,所以我猜您看到的是结构中的单词对齐

对齐-在32位体系结构上,以32位块的形式传递内存要高效得多。将一个短字符存储在16位中实际上不会节省任何内存,因为它仍然是相关32位字的一部分。

将另一个短字符添加到结构中会扩大大小,还是保持大小不变?我敢打赌它的尺寸是一样的


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

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


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

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

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

在节目作者阿纳尔多·卡瓦略·德梅洛的文章中阅读更多关于它的信息


网上的教程不多,但有些帮助。

正如dfa所说,这是因为对齐。一个有助于减小结构尺寸的“良好实践”是,从最大的构件开始,按构件的单个尺寸(实际上是它们各自的对齐方式,但尺寸通常足够好)对构件进行排序


这并不总是正确的,但大多数情况下都是如此。

有关计算数据成员偏移量的宏,请参见此处。这是一个不同的讨论,但是那里的宏起作用了…您不应该打印sizeof返回的带有%d的大小。类型si size_t,通常是无符号int或无符号long的typedef。它依赖于平台,因此必须先强制转换它,然后才能使用特定于类型的格式:“%u”,(无符号int)sizeof(…)或“%lu\n”,(无符号长)sizeof(…)。我相信C99增加了一种尺寸格式,这使事情变得简单多了。但通常结构中两条相邻的短裤会被打包在一起,因为通常的规则是使用填充物将每个构件按“自然”对齐。当然,整个问题都是由实现定义的行为,因此您的里程数会有很大的不同。如果并且仅当新的短字符插入到wlen成员附近,以便可以重复使用现有的填充字节时,里程数可能会保持不变。将其插入到几乎任何其他位置都可能会导致多出两个填充字节。