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 c1
和char 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 位,那么为什么要将指针值转换为 int
? int
在您的平台上是 64 位宽的吗?如果不是,您的减法可能会产生无意义的结果。为此目的使用 intptr_t
或 ptrdiff_t
,而不是 int
。
其次,在典型的实现中,无论您的平台是否为 64 位,1 字节类型通常会在 1 字节边界对齐。要查看 8 字节对齐,您需要 8 字节类型。为了查看它是如何对齐的,您必须检查地址的物理值(即它是否可以被 1、2、4、8 等整除),而不是分析两个变量之间的距离。
第三,c1
和c2
在内存中相距多远与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 实现可能会选择要求或不要求某些对齐方式,并结合选择使用或不使用各种指令。此外,在某些硬件上,是否支持未对齐访问可由操作系统配置。
我试图在我的 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 c1
和char 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 位,那么为什么要将指针值转换为 int
? int
在您的平台上是 64 位宽的吗?如果不是,您的减法可能会产生无意义的结果。为此目的使用 intptr_t
或 ptrdiff_t
,而不是 int
。
其次,在典型的实现中,无论您的平台是否为 64 位,1 字节类型通常会在 1 字节边界对齐。要查看 8 字节对齐,您需要 8 字节类型。为了查看它是如何对齐的,您必须检查地址的物理值(即它是否可以被 1、2、4、8 等整除),而不是分析两个变量之间的距离。
第三,c1
和c2
在内存中相距多远与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 实现可能会选择要求或不要求某些对齐方式,并结合选择使用或不使用各种指令。此外,在某些硬件上,是否支持未对齐访问可由操作系统配置。