在定义一个较为复杂的对象时,我们往往会使用结构体,那么结构体的大小该怎么计算呢?
#include<stdio.h>
typedef struct text
{
char a; //1
char b; //1
char c; //1
char d; //1
}text;
int main()
{
printf("%d",sizeof(text));
return 0;
}
如上,代码运算得到的结果是4个字节,好像是将所有的变量大小相加得到的。
#include<stdio.h>
typedef struct text
{
char a; //1
int b; //4
char c; //1
int d; //4
}text;
int main()
{
printf("%d",sizeof(text));
return 0;
}
运行得出16个字节,显然不是将所有变量大小相加得到。
#include<stdio.h>
typedef struct text
{
int b; //4
int d; //4
char c; //1
char a; //1
}text;
int main()
{
printf("%d", sizeof(text));
return 0;
}
将其变量换个顺序,结果得出12个字节,这到底是为什么?
——其实结构体有她自己的对齐规则。
结构体的对齐规则:
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8
- 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
以第二个结构体为例
首先a在结构体变量偏移量为0的地址处,
b要对齐到 4(对齐数)的整数倍的地址处(对齐数 4 = 编译器默认的一个对齐数 8 与 该成员大小 4 的较小值。 VS中默认的值为8),所以1,2,3浪费掉,从4开始占四个字节,
然后c对齐到1的整数倍的地址处,存到8,
然后存d同b一样,9,10,11浪费掉,从12开始存四个字节到15,
所以结构体大小等于 0~15 共占16个字节。
再来看第三个结构体
第三个结构体同理,b,d,c,a连续,但0~9为10个字节,而结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍,该结构体的最大对齐数为4,12为他的倍数,所以该结构体的大小为12个字节。
最后,默认对齐数可以修改,
如 #pragma pack(1) ,修改默认对齐数为1