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

Alignment in 64bit machine is not 8 Bytes

我试图在我的 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');
}

我期待 delta=8。因为是64位机器char c1char c2应该存储在8的倍数上,是不是?

即使我们假设编译器已经优化将它们存储在 less space 中,为什么不将它们背靠背存储 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);
}

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

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

第三,c1c2在内存中相距多远与char类型的对齐要求关系不大。它取决于 char 值在您的平台上的传递方式(或本地存储方式)。在您的情况下,它们显然每个都分配了 4 个字节的存储单元。那很好。没有人向你保证,两个不相关的 1 字节对齐的对象将尽可能紧密地紧挨着打包。

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

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

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

int main(void)
{
    printf("%zd bytes\n", _Alignof(max_align_t));
}

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

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