结构体大小计算
结构体大小的计算的依据是结构体内存对齐
对齐规则:
1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
(对齐数=编译器默认的一个对齐数与该成员变量大小的较小值。
VS 中默认的值为 8
Linux中gcc没有默认对齐数,对齐数就是成员自身的大小)
3.结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)的
整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构
体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。
例1:
//代码1
struct S
{
char a;//对齐数1
int i;//对齐数
char b;//对齐数1
};
由上图可见,第一个结构体成员对齐到偏移量为0处,大小为1字节,第二个结构体成员对齐数为4,对齐到偏移量4(4的倍数)处,第三个结构体成员对齐数是1,对齐到偏移量为8(1的倍数)处,总共偏移量到8处,总字节数是0~8为9个字节,但是又因为结果为最大对齐数的整数倍,最大对齐数是4,所以代码1的结果不是9字节,而是4的倍数12字节。
例2(结构体嵌套)
//代码2
struct S
{
double a;//对齐数 8
char b;//对齐数 1
int i;//对齐数 4
}s3;
struct T
{
char a;//对齐数 1
struct S s3;//对齐数 8
double b;//对齐数8
};
由上图可见,第一个结构体成员对齐到偏移量为0处,大小为1,第二个结构体成员是嵌套结构体T,根据上面的计算方法可得T的,最大对齐数是8,所以对齐到偏移量为8处(8的倍数),大小是16,第三个结构体成员对齐数为8,所以对齐到24处(8的倍数处),大小为8,所以最终偏移量为31,大小为0~31为32字节,为最大对齐数8的倍数,所以代码2的最终结果为32字节。
联合体
像结构体一样,联合体也是由一个或者多个成员构成,这些成员可以不同的类型。
但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所
以联合体也叫:共用体。
给联合体其中一个成员赋值,其他成员的值也跟着变化。(因为联合体共同用一块空间)
联合体大小计算
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
//代码1
#include <stdio.h>
union Un1
{
char c[5];//对齐数为1,数组相当于是5个char类型联合成员
int i;//对齐数为4
};
//代码2
union Un2
{
short c[7];//对齐数为2
int i;//对齐数为4
};
int main()
{
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));//8
printf("%d\n", sizeof(union Un2));//16
return 0;
}
代码1中,联合体的大小至少是最大成员的大小,所以至少为5字节,又因为当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍,所以该联合体大小为4的倍数为8个字节。
代码2中,联合体的大小至少为14字节,又因为当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍,所以该联合体大小为4的倍数16字节。