关于C语言中的内存对齐,以及在使用_Alignas说明符强制将变量对齐到一定字节数后如何分配内存,我有几个问题。
此代码在输出中显示每个已声明变量的内存地址:
#include <stdio.h>
int main(void)
{
unsigned char dx = 1;
unsigned char ca = 1;
unsigned char cx = 1;
unsigned char dz = 1;
unsigned char cb = 1;
unsigned char _Alignas(double) cz = 1;
char * p_begin = (char *) &cz;
char * p_end = (char * ) &dx + sizeof(dx);
printf("Addresses Value\n");
for (char * p = p_begin; p < p_end; p++)
{
printf("%9p %6X", p, 0xff & *p);
if (p == (char *) & dx) printf(" <- dx\n");
else if (p == (char *) & ca) printf(" <- ca\n");
else if (p == (char *) & cx) printf(" <- cx\n");
else if (p == (char *) & dz) printf(" <- dz\n");
else if (p == (char *) & cb) printf(" <- cb\n");
else if (p == (char *) & cz) printf(" <- cz\n");
else printf("\n");
}
return 0;
}在我的电脑上,输出如下:
Addresses Value
28ff08 1 <- cz
28ff09 FF
28ff0a 28
28ff0b 0
28ff0c CE
28ff0d 2A
28ff0e 40
28ff0f 1 <- cb
28ff10 1 <- dz
28ff11 1 <- cx
28ff12 1 <- ca
28ff13 1 <- dx
Process returned 0 (0x0) execution time : 0.016 s
Press any key to continue.在强制cz变量对齐8字节后,我期望看到的唯一行为是cz被分配给一个值是8的倍数的地址,我不希望看到从填充中跟随cz。为什么会有这样的行为?我还预计与填充相对应的字节数加上1字节的数据大小会得到8个字节,而填充占用6个字节,原因是什么?
发布于 2018-05-09 20:10:45
堆栈通常向下增长。这没有本质的原因,很大程度上是历史发展的结果。为堆栈分配一个内存区域,将堆栈指针设置为指向堆栈的高端,并启动程序的主例程。因为程序需要更多的堆栈空间,所以它减少了堆栈指针。
在您的示例中似乎发生的情况是,编译器按照遇到对象的顺序为对象分配空间。首先看到的是dx,因此会为它分配堆栈上的下一个可用空间0x28ff13。然后看到ca,并将其分配给0x28ff12。我们看到,随着堆栈的增长,它从较高的地址(开始的地址)到较低的地址。
当编译器到达您请求的8字节对齐的cz时,编译器跳转到下一个8的倍数(仍然是向下的方向),即0x28ff08。
当然,编译器可以考虑整个情况(而不是一次只查看一个对象),并将cz放在0x28ff10处,然后将其他对象放在它周围,从而使用更少的堆栈空间。如果在启用优化的情况下编译,编译器可能会这样做。另一方面,编译器可能要求在您的平台上保持堆栈指针对齐到8个字节(或更多),因此重新排列这些特定对象无论如何都不会节省任何堆栈空间。
在C标准中没有关于这方面的规则。编译器可以随心所欲地安排它的堆栈。
https://stackoverflow.com/questions/50248513
复制相似问题