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