64位机器的对齐不是8字节

dou*_*leE -2 c compilation cpu-architecture

我试图在我的64位机器上找到对齐方式(Intel iCore7上的Win10).我想到了这个实验:

void check_alignment(char c1, char c2 )
{
   printf("delta=%d\n", (int)&c2 - (int)&c1); // prints 4 instead of 8
}

void main(){
    check_alignment('a','b');
}
Run Code Online (Sandbox Code Playgroud)

我在期待delta=8.因为它是64位机器char c1,char c2应该存储在8的倍数.不是吗?

即使我们假设编译器已经进行了优化以将它们存储在更小的空间中,为什么不将它们背靠背存储delta=1呢?为什么4字节对齐?

我用float类型重复了上面的实验,但仍然给出了delta=4

void check_alignment(float f1, float f2 )
{
   printf("delta=%d\n", (int)&c2 - (int)&c1); // prints 4
}

void main(){
    check_alignment(1.0,1.1);
}
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 6

首先,如果您的平台是64位,那么为什么要将指针值转换为intint您的平台上有64位宽吗?如果不是,您的减法可能会产生毫无意义的结果.使用intptr_tptrdiff_t为此目的,不是int.

其次,在典型的实现中,1字节类型通常在1字节边界处对齐,无论您的平台是否为64位.要查看8字节对齐,您需要一个8字节类型.并且为了看它是如何对齐的,你必须检查地址的物理值(即它是否可以被1,2,4,8等整除),而不是分析两个变量间隔多远.

第三,c1c2记忆的距离与记忆的距离与char类型的对齐要求几乎没有关系.它取决于char值如何在您的平台上传递(或存储在本地).在您的情况下,它们显然分配了4字节的存储单元.那很好.没有人向你承诺,两个不相关的1字节对齐对象将尽可能紧密地彼此相邻打包.

如果要通过测量两个对象的存储距离来确定对齐方式,请声明一个数组.不要试图测量两个独立物体之间的距离 - 这是没有意义的.


Eri*_*hil 5

要确定C实现中最基本的对齐方式,请使用:

#include <stdio.h>
#include <stddef.h>

int main(void)
{
    printf("%zd bytes\n", _Alignof(max_align_t));
}
Run Code Online (Sandbox Code Playgroud)

要确定任何特定类型的对齐要求,请max_align_t在上面替换该类型.

对齐不仅仅是处理器或其他硬件的功能.硬件可能支持具有不同性能影响的对齐或未对齐访问,某些指令可能支持未对齐访问,而其他指令则不支持.特定的C实现可以选择要求或不要求某些对齐与选择使用或不使用各种指令相结合.此外,在某些硬件上,操作系统是否可以配置是否支持未对齐访问.