什么是字节对齐
在现代计算机中,内存空间都是按照字节划分,理论上可以从任何起始地址访问任何变量,但是在实际中访问特定变量时经常在特定的内存地址中的访问(例如访问结构体中的指定变量),这时就需要各种数据类型按照一定的规则在内存中存放,而不是一个一个顺序的存放,这就是对齐。
对齐的作用
- 通过合理的内存对齐可以提高访问效率
- 合理利用字节对齐可以有效的节省内存空间
结构体对齐
在C语言中,结构体是一种复合数据类型,其构成元素可以是基本的数据类型(char int long 等),也可以是一些复合型数据类型(数组 结构体 联合)的数据单元。编译器为结构体中的成员按照对齐字节的规则分配空间,各成员按照他们被声明的顺序在内存中顺序存储。第一个成员的地址与整个结构体的地址相同。
看下面的例子(32位,X86处理器,GCC编译器)
struct A{
int a;
char b;
short c;
};
struct B{
char b;
int a;
short c;
};
在32位机器上各数据类型的长度位:char 1字节,int 4字节, short 2字节。
sizeof(A)等于4,sizeof(B)等于12。
结构体A中包含一个4字节的int数据,一个1字节char数据和一个2字节short数据;B也一样。按理说A和B大小应该都是7字节。之所以出现上述结果,就是因为编译器要对数据成员在空间上进行对齐。
字节对齐准则
- 数据类型自身的对齐值:char型数据自身对齐值为1字节,short型数据为2字节,int/float型为4字节,double型为8字节。
- 结构体或类的自身对齐值:其成员中自身对齐值最大的那个值。
- 指定对齐值:#pragma pack (value)时的指定对齐值value。
- 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小者,即有效对齐值=min{自身对齐值,当前指定的pack值}。