目录
成员均为内置类型的结构体
先分析一段代码
#include<stdio.h>
struct A
{
char c;
int a;
};
struct B
{
char a;
char b;
char c;
int d;
};
int main()
{
printf("%d\n", sizeof(struct A));
printf("%d\n", sizeof(struct B));
return 0;
}
那结构体B是不是比结构体A更大呢?(毕竟B里面的成员更多啊)
运行结果:
很可惜不是的,两者一样大!可是B里面明明比A多了两个char类型啊!这就要谈到结构体对齐了
规则: (3条)
- 结构体的第⼀个成员打头,从0位置开始对齐。就比如上述结构体A,第一个成员是char类型
- 其他成员要对齐到对齐数的整数倍。对齐数=编译器默认对齐数与该变量大小的较小者。比如结构体A的第二个变量,是int类型,大小是4字节,我用的VS2022默认对齐数是8,取两者中的较小者就是4,所以结构体A的第二个变量应当对齐至4的整数倍。
- 结构体的总大小为最大对齐数的整数倍。(结构体每个成员都有各自的对齐数,取里面最大的那个)。比如结构体A两个成员:char类型占1字节,编译器默认对其数是8,所以char对齐数是1,同理int对齐数是4,取其中的最大值4,所以结构体A的大小应当是4的整数倍。
0~7总共有8字节,刚好是4的倍数,所以struct A的大小就是8
那我们再来练习一道
struct C
{
int a;
double b;
char c;
};
1、成员a:从0对齐,占4字节。
2、成员b:大小是8字节,编译器默认对齐数是8,所以b的对齐数是8,从8的整数倍开始对齐
中间4~7是浪费掉的空间
3、成员c:大小是1字节,编译器默认对齐数是8,所以c的对齐数是1,从1的整数倍开始对齐
4、三个成员中对齐数最大的是b,对齐数是8,所以struct C的大小应该是8的倍数,0~16总共是17个字节,不是8的倍数,那就要继续浪费空间,开够24个就可以了,刚好是8的3倍。
所以struct C所占的空间是24字节。
嵌套结构体
下面再来分析一段代码
struct A
{
int* p;
int a;
};
struct B
{
struct A aa;
int c;
};
struct C
{
int* p;
int a;
int c;
};
int main()
{
printf("%d\n", sizeof(struct A));
printf("%d\n", sizeof(struct B));
printf("%d\n", sizeof(struct C));
return 0;
}
读者可以先计算一下struct A的大小 (注意64位下指针变量占8字节,32位下占4字节)。 结构体B跟C的大小一样吗?
运行结果(64位,编译器默认对齐数是8)
struct A对齐方式:
嵌套结构体对齐数是自己成员中的最大对齐数。比如struct A中的成员最大对齐数是8,所以struct A的对齐数就是8。
计算struct B可以把 struct A aa 这个成员看成:大小是16字节、对齐数是8的一个东西。
0~23总共24个字节,这样下来struct B的大小就是24字节了。
修改默认对齐数
#pragma pack(1) //将默认对其数修改为1
#include<stdio.h>
struct A
{
int a;
double b;
};
int main()
{
printf("%d\n", sizeof(struct A)); //输出:12
return 0;
}
以上就是结构体对齐方式了!
为什么要对齐?
emmm,拿空间换时间!