关于数据类型对齐的怀疑,我现在正在学习对齐,还有一些问题,所以我知道在用gcc编译i386体系结构时,linux中double对齐为4个字节,因此double的地址与a对齐4的倍数,但只有在使用数据结构时,才会在使用堆栈时发生
#includeint main(void) { double x = 5; // 8 char s = 'a'; // +1 double y = 2; // ---- = 9 + 8 = 17 + alignment = 20 //int x = 5; // 4 //char s = 'a'; +1 //int y = 2; --------= 5 + 4 = 9 + alignment = 12 size_t a, b; a = (size_t)&s; b = (size_t)&y; printf("%zu", a - b); // it wasn't supposed to be 11 instead of 15 return 0; }
编译:$ gcc -m32 -o align align.c
出于最佳化的考虑,编译器可以而且确实会选择给予对象更多的对齐方式,除非ABI的结构打包规则强迫它们将其对齐。 alignof(double) = 4
适用于i386 System V,但gcc 更喜欢使其自然对齐,例如aligas(sizeof(double)) double x
。
现代x86 确实受益于的8字节对齐 另外,将堆栈对齐16可以使本地代码便宜8或16字节对齐,这是对i386 System V ABI的最新Linux修改。在此之前,每个带有 IDK为什么您认为编译器会按照声明的顺序排列本地语言,就像它是一个结构一样。编译器可以自由地将大对象放在一起,因此不必在填充上浪费空间。 查看编译器的asm输出,以了解其堆栈布局的情况。并且不要忘记启用优化。您可能double
,但是alignof(double) == 4
ABI规则在386天没有缓存时就有意义了,并且fld qword [mem]
确实需要2个单独的32位负载。但是,如果现代x86硬件没有在两条缓存行之间拆分,则可以在一次访问缓存中完成8字节(甚至32字节)的加载,这可以通过alignof double
局部函数的函数都将被迫制作一个帧指针,然后执行and $-8, %esp
某些操作。
volatile double
用来阻止其内存地址进行优化。