#include <stdio.h>
int main(void)
{
char c1 = '0';
char _Alignas(double) c2 = '0';
printf("char alignment: %zd\n", _Alignof(char));
printf("double alignment: %zd\n", _Alignof(double));
printf("&c1: %p\n", &c1);
printf("&c2: %p\n", &c2);
return 0;
}在我的环境中运行,结果是:
char alignment: 1
double alignment: 8
&c1: 000000000061FE1F
&c2: 000000000061FE18由gcc 8.1.0版本编译(x86_64-posix seh-rev0,由MinGW-W64项目构建)。
我想知道为什么&c2和&c1之间的字节数是7,而不是8(在我的环境中是sizeof(double))?
发布于 2021-09-14 04:11:30
为什么char _Alignas双倍大小不是8?
对齐意味着地址是某个值的倍数。它与变量的大小无关。_Alignas(8)表示地址将是8的倍数,即以十六进制的0或8结尾
我想知道为什么&c2和&c1之间的字节是7,而不是8(在我的环境中,大小为双精度)?
未指定堆栈上变量的位置。编译器可以自由地将c1放在c2之前或之后。这里唯一的要求是c2必须是8的倍数。如果c1是8的倍数,并且编译器选择将c2放在8的倍数之后,那么将使用7字节的填充。但是它们显然可以将c1放在c2之前,并且它们的地址仅相差1。您可以很容易地看到each compiler puts the variables in different positions with different distances
有关更多细节,请阅读
发布于 2021-09-14 04:00:29
对齐确定地址的位置,而不是它们将占用的空间大小。
一个char只占用1个字节,即使它在8个字节的边界上对齐。在c1和c2之间有6个未使用的字节。
通常,对齐和大小是相同的,或者将对齐四舍五入为2的幂。这是因为在许多架构上,可能需要多个获取指令才能从未对齐的内存地址中检索。
在您的示例中,c1在1字节边界上对齐,因此它被放置在堆栈上的第一个可用位置。
c2在8字节边界上对齐,因此它跳过所需的字节数,直到地址在8字节边界上对齐。这意味着(地址% 8) == 0。如果c2的类型是double,它将需要移动到下一个对齐的地址,提前8个字节,但由于它只是一个char,所以它正好适合第一个8字节的边界。(编辑:正如其他人所指出的,编译器可以重新排列变量,在这种情况下很可能会这样做)
对齐方式可以大于或小于元素的大小。
在某些架构上,您只需在2或4字节边界上对齐即可。计算机根本不能寻址“中间字节”。不需要地址线,所以如果对齐4个字节的地址(并且总是读取4个字节),那么只需使用14个地址线就可以寻址2^16字节的内存。这可以减少存储器总线所需的大小。
https://stackoverflow.com/questions/69171393
复制相似问题