Struct和Union字节对齐的内存占用计算方法

1.基本概念

有四个概念需要理解:
A、数据类型自身的对齐值:
   是指对该数据类型使用sizeof()操作符进行操作所得到的大小(单位,字节);比如,对于[unsigned] char类型的数据,其自身对齐值为1字节;对于[unsigned] short类型的数据,其自身对齐值是2字节;对于[unsigned] int、[unsigned] long、[unsigned] l、float、等数据类型,其自身对齐值是4字节;double long 其自身对齐值为8;
B、结构体、联合体、类的自身对齐值:
   是指其所有基本类型的成员中,自身对齐值最大的那个值;如果这些复合类型中有嵌套类型或复合类型的变量,则需要把这些嵌套的类型或复合类型的变量拆解成基本类型的成员之后再对齐;
C、指定对齐值:
   是指使用预处理指令#pragma pack(align_value)指定的对齐值align_value;
D、数据成员、结构体和类的有效对齐值:
   是指其自身对齐值和指定对齐值中较小的那个值;
其中,有效对齐值是最终用来决定数据存放地址方式的值,最重要;设定有效对齐值为N,就表示"对齐在N字节上",也就是说,该数据的"存放起始地址%N=0";

因此,每个类型的数据的有效对齐值就是其自身对齐值(通常是这个类型的大小)和指定对齐值(不指定则取默认值)中较小的那个值,并且结构体自身对齐值是其所有成员中自身对齐值最大的那个值;

1.struct的每个成员变量都需要对其,其对齐方式是按照自身对其值和指定对齐值得较小值来决定。

    例如使用#pragma pack(4)定义了指定对齐值为4

#pragma pack(4) //指定对齐值为4
struct test
{
   char name[10];
   double age;
}
#pragma pack() //恢复默认对其值

在上面示例结构体中

char name[10],是一个char数组,自身对齐值是1,指定对齐值是4,而1<4,即自身对齐值小于指定对齐值,因此选择找较小值作为有效对齐值,即1,选择偏移量0为数组的起始地址。0-9为数组的地址。

再看 double age;自身对齐值为8,同理选择自身对齐值和指定对齐值较小的最为有效对齐值,因此其有效对齐值为4。所以成员变量的起始地址必须为4的倍数,所以需要补全10 11两个字节,从12开始存放age变量。因此age的地址为12-19。

再看结构体的自身对齐值,正如前面所说,其自身对齐值取其成员变量中最大的自身对齐值,因此在这个,也就是age的自身对齐值,8。因此,整个结构体占用的有效字节为20个字节;由于结构体整体的对齐值和大小是其最宽基本类型成员大小的整数倍,即:按照最宽基本类型成员大小和指定对齐值中较小的值对齐的;因为结构体最宽基本类型成员的大小是4字节,其有效对齐值也是4字节,而20字节按照4字节圆整的结果是20字节,所以,sizeof(test)=20;

2.union

和struct不同的是它不需要每个成员变量都对其。但要保证其内存要大于最大成员占用的字节长度,同时保证是有效对齐值的倍数。

union test
{
   char name[10];
   double age;
}

如事例代码所示:char name[10]要占用10个字节,其自身对齐值为1,age要占用8个字节,其自身对齐值为8

因此union的自身对齐值为8,如果没有指定对齐值则有效对齐值取自身对齐值,因此其有效对齐值==自身有效值==8,所以Union的size既要满足>=10,又要满足是8的倍数,因此sizeof(test)=16

猜你喜欢

转载自blog.csdn.net/fanxin_i/article/details/80997897