1. 对齐的原因与作用
1.1. 对齐的原因
各种硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的 CPU 在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。
1.2. 对齐的作用
最常见的情况是,如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个 int 型(假设为 32 位系统)存放在偶地址开始的地方,那么一个读周期就可以读 32bit ,而如果存放在奇地址开始的地方,就需 2 个读周期,并对两次读出的结果的高低字节进行拼凑才能得到 32bit 数据。显然在读取效率上下降很多。
如果都按照该 cpu 对齐格式对齐了的话,可以大大减少 cpu 读周期的数目,明显提高了运算的效率。
在 x86 上,类似的操作只会影响效率,因为 x86 支持自动对齐。但是在 MIPS 或者 sparc 上,可能就是一个 error ,因为它们要求必须字节对齐。
2. 对齐的实现
通常,我们写程序的时候,不需要考虑对齐问题。编译器会替我们选择适合目标平台的对齐策略。当然,我们也可以通知给编译器传递预编译指令而改变对指定数据的对齐方法。
但是,如果我们从不关心这个问题,在有些情况下可能会出错。比如第三方库、 IPC 之间发送内存数据、二进制网络协议等等,有可能使用不同的编译器并设置不同的字节对齐方式,因此就有可能带来一些莫名其妙的错误,对于相同的结构体或类对象 sizeof 出来的大小可能差别很大。
3. 字节对齐对程序的影响
先让我们看几个例子吧 (32bit,x86 环境 ,gcc 编译器 ):
设结构体如下定义:
struct A
{
int a;
char b;
short c;
};
struct B
{
char b;
int a;
short c;
};
现在已知 32 位机器上各种数据类型的长度如下 :
char:1( 有符号无符号同 )
short:2( 有符号无符号同 )
int:4( 有符号无符号同 )
long:4( 有符号无符号同 )
float:4
double:8
那么上面两个结构大小如何呢 ?
结果是 :
sizeof(strcut A) 值为 8
sizeof(struct B) 的值却是 12
结构体 A 中包含了 4 字节长度的 int 一个, 1 字节长度的 char 一