C结构体的64位对齐/填充?

4
struct tag_t_ {
    u_int8_t op;
    u_int8_t num;
    u_int32_t labels[5];
};

在上述结构中,64位编译器会在哪里添加填充字节?是在第一个标签之前还是在第一个标签的末尾?如果填充在第一个标签的末尾,那么在32位架构中访问(读取)第一个标签时是否会导致错误的结果?
3个回答

5

我正在64位系统上运行--该结构体的内存映射如下:

offset:  variable
     0:  op num     
     2:  00 00   // only 2 paddings
     4:  label0
     8:  label1
         ...
    20:  label5

sizeof(struct) == 24

// 在这里,可以在字符和第一个32位整数之间放置一个unsigned short,而不会影响结构体的大小。

结构体填充规则是,任何宽度为W的基本变量都将对齐到该宽度。将double作为第二个参数会导致op后面有7个填充字节,在num后面只有3个填充字节,因为labels[0]将从可被4整除的偏移量开始。

32位系统与64位系统之间存在差异:32位系统仍将8字节变量对齐到32位边界。64位系统将long int和double对齐到8字节边界。

这使得在32位系统中使用该结构体是安全的。如果结构体中有double,可以通过谨慎规划变量使结构体兼容。


4
这取决于编译器,没有普适的规则可以应用并保证可行。关于问题的后半部分,我不确定,因为在32位体系结构上编译器会不同。直接传输结构永远不是一个好主意。由于填充,如果你在64位机器上写入sizeof (tag_t_)字节到某些外部介质,然后传输介质并尝试在32位机器上读取sizeof (tag_t_),它将失败。所以不要这样做。按字段序列化结构,并以相同的方式反序列化它们。

+1 是因为在系统之间选择传输结构体是填充相关问题的主要原因。 - Lindydancer

0

填充通常应用于每个字段的末尾。否则,64位编译二进制文件与32位二进制文件不兼容。因此,您可能需要重新编译所有内容以适用于32位架构。

然后,32位编译器将处理对齐,并相应地生成地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接