struct tag_t_ {
u_int8_t op;
u_int8_t num;
u_int32_t labels[5];
};
在上面的结构中,64 位编译器会在哪里添加填充字节?
它是在第一个标签之前还是在第一个标签的末尾?
如果填充位于第一个标签的末尾,在访问(读取)32 位拱门中的第一个标签时会导致任何错误结果吗?
这取决于编译器,没有可以应用并保证成立的通用规则。
我不确定问题的后半部分,因为在 32 位架构上,编译器当然会有所不同。直接转移结构从来都不是一个好主意。
因为填充的原因,如果你sizeof (tag_t_)
在 64 位机器上向某些外部媒体写入字节,传输媒体,然后sizeof (tag_t_)
在 32 位机器上尝试读取,就会失败。所以不要那样做。逐个字段序列化结构,并以相同的方式反序列化它们。
我在 64 位系统中运行它——结构的内存映射是
offset: variable
0: op num
2: 00 00 // only 2 paddings
4: label0
8: label1
...
20: label5
大小(结构)== 24
// 这里可以在字符和第一个 32 位整数之间放置一个无符号短整数,而不会影响结构的大小。
结构填充的规则是宽度为 W 的任何基本变量都将与该宽度对齐。双倍作为第二个参数将导致 7 个填充字节之后op
,并且只有 3 个填充字节之后num
,因为标签 [0] 然后将从可被 4 整除的偏移量开始。
32/64 位系统之间存在差异:32 位系统仍会将 8 字节变量与 32 位边界对齐。64 位系统会将 long int 和 double 对齐到 8 字节边界。
这将使在 32 位系统中使用该结构变得安全。如果结构中有双精度数,仍然可以使结构与变量的仔细规划兼容。
填充通常应用在每个字段的末尾。不,64 位编译的二进制文件与 32 位二进制文件不兼容。因此,您可能必须为 32 位架构重新编译所有内容。
然后对齐将由 32 位编译器进行处理,并相应地生成地址。