1. 什么是对齐?
当你定义一个变量时,系统会给这个变量分配一段连续的空间。而由于CPU寻址的特殊性,32位 CPU 只能以 4 的整数倍来寻址。因此,如果一个变量被分配在两个不同的 4 字节块中,那么 CPU 就要读取两次,再将这个变量拼凑完成。为了 CPU 执行效率更高,需要进行字节对齐。
2. 对齐方式
对齐是为了 CPU 能够更高效率运行的,因此对齐的方式与CPU的类型密切相关。
2.1 64 位机器默认对齐
在64位操作系统上,如下数据结构占用的存储空间大小为多少字节:
struct A{
unsigned int a;
char b[2];
double c;
short d;
}
如果做一下简单的加法:4 + 2 + 8 + 2 = 16 显然是不对的。在 64 位机器上,复杂结构类型的对齐数为成员中占用空间最大的字节数,也就是 sizeof(double) = 8。因此 A 的结构为如下形式:
地址:| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
{|------a---------|-----b----|不够c}{--------------------c---------------------------}{|----d------|----------------补充----------------------}
| 第一次分配 8 个字节| 补充 | 第二次分配8字节 第三次分配 8 字节
所谓 8 字节对齐便如上图所示。因此执行sizeof(A),将会得到 8 + 8 + 8 = 24
。
亦或者是
struct test
{
char a[3];
int b;
char c;
};
为 4 字节对齐,执行sizeof(test),得到3 + (1) + 4 + 1 + (3) = 12
2.2 32 位机器默认对齐
32位机器上字节对齐与 64 位相类似,唯一不同之处在于 32 位机器对齐数只能 小于等于4(默认为4)。因此
struct test
{
int a;
float b;
char c;
}
sizeof(test) = 12。4 + 4 + 1 +(3)
struct test2
{
short a;
float c;
}
sizeof(test2) = 8。2 + (2) + 4