为什么要字节对齐? 在一些特定处理器上只能从特定的地址开始存取。 从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列。 而需要字节对齐的根本原因在于CPU访问数据的效率问题。若结构体按字节对齐,可在很大程度上提高程序执行的效率。 比如在32位cpu下,假设一个4字节整型变量的地址为0x00000004,那它就是自然对齐的(地址从0x00000000开始)。假设一个整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取它的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到所要的数据,如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。
在32位cpu下,分析如下结构体占用多少字节?
struct test
{
char x1;
short x2;
float x3;
char x4;
};
由于编译器默认情况下会对这个struct作自然边界对齐,结构的第一个成员x1,其偏移地址为0,占据了第1个字节。第二个成员x2为short类型,其起始地址必须2字节对界,因此,编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然边界地址上,在它们前面不需要额外的填充字节。在test结构中,成员x3要求4字节对界,是该结构所有成员中要求的最大边界单元,因而test结构的自然对界条件为4字节,编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。 相关函数: 1、 attribute((aligned(n)))
struct stu{
char sex;
int length;
char name[10];
}__attribute__ ((aligned (1)));
struct stu my_stu;
则sizeof(my_stu)可以得到大小为15。
上面的定义等同于
struct stu{
char sex;
int length;
char name[10];
}__attribute__ ((packed));
struct stu my_stu;
__attribute__((packed)) 得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐.
2、 pragma pack()
#pragma pack(1)
struct test
{
char x1;
short x2;
float x3;
char x4;
};
#pragma pack()
这时候sizeof(struct test)的值为8。
3、显式的插入reserved成员 有一种使用空间换时间做法是显式的插入reserved成员: struct A{ char a; char reserved[3];//使用空间换时间 int b; } reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.
参考链接: https://www.cnblogs.com/ransn/p/5081198.html
|