什么是字节对齐
对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。
结构的自然对齐:
struct test
{
char x1;
short x2;
float x3;
char x4;
};
- 第一个成员x1,其偏移地址为0,占据了第1个字节。
- 第二个成员x2为short类型,其起始地址必须2字节对界,因此,编译器在x2和x1之间填充了一个空字节。
- 结构的第三个成员x3和第四个成员x4恰好落在其自然边界地址上,在它们前面不需要额外的填充字节。
- 在test结构中,成员x3要求4字节对界,是该结构所有成员中要求的最大边界单元,因而test结构的自然对界条件为4字节,编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。
为何要自然对齐
对齐的作用和原因:
- 各个硬件平台对存储空间的处理上有很大的不同。
- 一些平台对某些特定类型的数据只能从某些特定地址开始存取。
比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。显然在读取效率上下降很多。
如何处理对齐
- 标准数据类型 – – – 保证地址为其数据长度整数倍
- 数组 – – – 按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。
- 联合 – – – 按其包含的长度最大的数据类型对齐。
- 结构体 – – – 结构体中每个数据类型都要对齐。
使用__attribute__
我们可以按照自己设定的对齐大小来编译程序,GNU使用__attribute__选项来设置,比如我们想让刚才的结构按一字节对齐,我们可以这样定义结构体。
struct stu{
char sex;
int length;
char name[10];
}__attribute__ ((aligned (1)));