#include <stdio.h>
#include <stddef.h>
struct struct_a {
int x;
float y;
char a;
double z;
};
int main(void) {
printf("sizeof struct %zu\n", sizeof(struct struct_a));
printf("Offset of x: %lu\n", offsetof(struct struct_a, x));
printf("Offset of y: %lu\n", offsetof(struct struct_a, y));
printf("Offset of a: %lu\n", offsetof(struct struct_a, a));
printf("Offset of z: %lu\n", offsetof(struct struct_a, z));
return 0;
}
-m64
选项):sizeof struct 24
Offset of x: 0
Offset of y: 4
Offset of a: 8
Offset of z: 16
padding的7个字节在偏移16处对齐
a
(8的倍数)。
z
选项):
-m32
sizeof struct 20
Offset of x: 0
Offset of y: 4
Offset of a: 8
Offset of z: 12
总结构大小为20字节
,它是8个倍数,而结构元素可能并不总是在数组中自然对齐。问题:
a
z
将与8字节边界对齐,但是在32位模式下,它是在12上对齐的。我了解一个32位系统在每个周期中处理
double
?的一致性。
我已经检查了以下堆栈溢出讨论,但是它们似乎更复杂,因为我试图从初学者中理解。
带有UINT64_Tdouble
gdb的记忆布局-M32编译二进制
double
i我试图将一个宣布为2个元素的数组,并且没有严格的数据对齐其倍数。
// use the same struct_a form the above code,
a.x = 0xFFFFFF; // 2 nibble should show 0x00 and rest all 0xff
a.c = 'A';
*(uint32_t *)&a.y = 0xFFFFFFFF; // Force 0xff bytes for float
*(uint64_t *)&a.z = 0xFFFFFFFFFFFFFFFF; // Force 0xff bytes for double
$1 = {x = 16777215, y = -nan(0x7fffff), c = 65 'A', z = -nan(0xfffffffffffff)}
(gdb) x/20bx &a
0x56559008 <a>: 0xff 0xff 0xff 0x00 0xff 0xff 0xff 0xff
0x56559010 <a+8>: 0x41 0x00 0x00 0x00 0xff 0xff 0xff 0xff
0x56559018 <a+16>: 0xff 0xff 0xff 0xff
// 0x56559008 x, 0x56559008 y, 0x56559010 a, < 3 byte padding >, 0x56559010 z.
(gdb) p &a.x
$6 = (int *) 0x56559008 <a>
(gdb) p &a.y
$7 = (float *) 0x5655900c <a+4>
(gdb) p &a.c
$8 = 0x56559010 <a+8> "A"
(gdb) p &a.z
$9 = (double *) 0x56559014 <a+12>
(gdb) x/40bx &a
0x56559040 <a>: 0xff 0xff 0xff 0x00 0xff 0xff 0xff 0xff
0x56559048 <a+8>: 0x41 0x00 0x00 0x00 0xff 0xff 0xff 0xff
0x56559050 <a+16>: 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x00
0x56559058 <a+24>: 0xff 0xff 0xff 0xff 0x41 0x00 0x00 0x00
0x56559060 <a+32>: 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
(gdb) p &a[0].z
$2 = (double *) 0x5655904c <a+12>
(gdb) p &a[1].x
$3 = (int *) 0x56559054 <a+20>
$1 = {x = 16777215, y = -nan(0x7fffff), c = 65 'A', z = -nan(0xfffffffffffff)}
(gdb) x/24bx &a
0x555555558010 <a>: 0xff 0xff 0xff 0x00 0xff 0xff 0xff 0xff
0x555555558018 <a+8>: 0x41 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x555555558020 <a+16>: 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
// 0x555555558010 x, 0x555555558014 y, 0x555555558018 c, < 7 byte padding >, 0x555555558020 z
(gdb) p &a.x
$2 = (int *) 0x555555558010 <a>
(gdb) p &a.y
$3 = (float *) 0x555555558014 <a+4>
(gdb) p &a.c
$4 = 0x555555558018 <a+8> "A"
(gdb) p &a.z
$5 = (double *) 0x555555558020 <a+16>
a[0].x = 0xFFFFFF; a[1].x = 0xFFFFFF;
a[0].c = 'A', a[1].c = 'A';
*(uint32_t *)&a[0].y = 0xFFFFFFFF; // Force 0xff bytes for float
*(uint32_t *)&a[1].y = 0xFFFFFFFF; // Force 0xff bytes for float
*(uint64_t *)&a[0].z = 0xFFFFFFFFFFFFFFFF; // Force 0xff bytes for double
*(uint64_t *)&a[1].z = 0xFFFFFFFFFFFFFFFF; // Force 0xff bytes for double
a[0].z
它从数组元素的0x555555558050 <a+16>
a[1].x
Https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
文件表3.1第12.1页上的第12页。编译器根据规范创建结构。所有编译器都使用相同的规格,因此生成的代码可以相互交谈。这会影响双重对齐吗?
最好在8上对齐双打。但是ABI是IT。