前言
对于结构体、位段、枚举、联合体大小的计算,这里先给出四道题目,如果你都做对了,说明你对自定义类型大小的计算没什么问题了,就没有继续看这篇文章的必要了。
注:对齐数默认为8
(一)结构体
struct s1{
double d1;
char c1;
int i;
};
struct s2{
char c2;
struct s1 s;
double d2;
};
printf("%d %d\n", sizeof(struct s1),
sizeof(struct s2));
(二)位段
struct s3{
char a:2;
char b:4;
char c:5;
char d:4;
};
struct s3 s3={0};
s3.a=10;
s3.b=12;
s3.c=3;
s3.d=4;
char *i=(char*)&s3;
printf("%d %d\n",sizeof(struct s3),*i);
(三)枚举
enum s4{
RED,
BLUE,
GREEN=INT_MAX+1;
};
printf("%d\n",sizeof(enum s4));
(四)联合体
union s5{
short s[7];
int i;
};
printf("%d\n",sizeof(union s5));
下面直接公布答案
(一)
16 32
(二)
3 50
(三)
4
(四)
16
正文
结构体
结构体对齐原则:
1.第一个成员在结构体偏移量为0的地址处
2.其他结构体成员要对齐到对齐数的整数倍处
对齐数为编译器默认的对齐数与该结构体成员的较小值
· VS默认对齐数的值为8
· 对齐数的大小可以通过以下指令修改
#pragma pack(4) //修改对齐数的值为4
· linux没有默认对齐数,默认对齐数就是结构体成员自身的大小
3.结构体总大小为最大对齐数(因为每个成员都有一个对齐数)的整数倍
4.嵌套的结构体对齐到自己最大对齐数的整数倍处,结构体的总大小是所有最大对齐数(包括嵌套结构体的对齐数)的整数倍
规则看上去有点多且难以理解,不过没有关系,下面通过分析一些例子,等你在返回来看时就会很容易理解了
struct s1
{
char c1;
int i;
char c2;
};
struct s2
{
short s;
struct s1 s1;
char c;
};
相信通过以上例题,你已经基本了解了结构体大小的计算
这里需要注意的是,对数组类对齐数要取数组的成员(可以看作数组类型大小)与默认值的较小者,如结构体中int arr[7]这个成员的对齐数是4
位段
位段的声明与结构体类似,但有两点不同:
1.位段的结构体成员必须是整型家族
2.位段成员后面有一个冒号和数字(代表比特位)
这里需要注意的是位段是不跨平台的,不同平台对位段的处理不同,我这里使用的是VS2022
位段大小计算原则:
1.当前一个成员还有剩余没有使用的比特位时,如果可以容下下一个成员,则直接使用上个成员未使用的比特位,否则直接使用下一个完整的字节
2.其余规则与结构体类似,也有对齐数
直接看例题就行了
struct s3
{
char c1 : 2;
char c2 : 4;
char c3 : 5;
int i;
}s3;
s3.c1=1;
s3.c2=24;
char *c=(char*)&s3;
printf("%d",sizeof(s3));
printf("%d",*c);
枚举
枚举变量的大小,实质是常数所占内存空间的大小(常数为int类型,当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节),枚举类型所占内存大小一般就是4个字节
enum s4 {
GREEN = 6,
RED,
BLACK
};
printf("%d",sizeof(enum s4));
这个直接就是4了
联合体
联合体大小计算为:
- 选取占用字节最大的成员
- 联合体大小为对齐数的整数倍
union s5
{
char c[5];
int i;
};
union s6
{
char c[5];
short i;
};
printf("%d %d\n",sizeof(s5),sizeof(s6));
打印:8 6
结语
相信通过上面的例题,你自己也可以算出答案。如果本文写得有什么不对的地方,恳请指正。最后,如果你觉得本文对你有帮助,不要忘记点赞收藏加关注哦!