不用sizeof怎么直接看出来结构体的大小?——C语言
不用sizeof怎么直接看出来结构体的大小?——C语言
在C语言中,理解结构体的内存布局和对齐规则对于优化程序性能至关重要。本文将通过具体的代码示例,详细讲解如何在不使用sizeof运算符的情况下,计算结构体的大小。
下面的这道题你会吗?
typedef struct{
int a;
char b;
short c;
short d;
}AA_t;
如果你一脸懵逼,证明你来对地方了,如果你轻松拿捏了这类问题,那么请你节约这点时间去学点别的。
想要得到一个结构体的大小就必须了解一个知识点,结构体的内存对齐
结构体的内存对齐是有一定规则的,我们先来看一下对齐规则:
- 结构体的第一个成员对齐到结构体变量起始位置偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数= 编译器默认的对齐数 与 该成员变量的大小的较小值 - 结构体的总大小为 最大对齐数(结构体成员变量中对齐数最大的那一个)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员变量中最大对齐数的整数倍,结构体的整体大小就是所有最大对齐数(函嵌套结构体中的成员的对齐数)的整数倍。
可能你看完后会很晕,跟个绕口令一样,没关系,接下来我们来看几个例子。
以下面的结构体为例。
struct S1
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S1));
我们假设右边的是我们电脑的一部分内存空间,一个方格为一个字节,假设我们的结构体的内存从红色箭头后开始开辟。
对齐规则1的意思是,结构体的空间从哪个地址开始,那么第一个成员变量就正正好好的存到哪里,这样偏移量就是0了
在我们的结构体struct S1中,第一个成员变量为 char,占一个字节,所以直接放上去。
接下来我们再来看第二个成员变量,它的类型int。
这个时候就需要用到我们的对齐规则2了。
我们先计算它的对齐数,由于整型int占4个字节,默认对齐数为8(题目里规定了),所以取较小值 对齐数为4。(重点:除了第一个成员变量的其他成员都需要与默认对齐数取较小值)
接下来就是关键的一步,我们需要将成员变量对齐到 对齐数的整数倍。
1 、2、 3都不是4(int 的对齐数)的整数倍,4是,所以int类型被放在了绿色区域,会跳过三个小方块,由于int占四个字节,所以有四个绿色的小方块
接下来再来看我们的第三个成员变量,由于是char 类型的,所以对齐数为 8 (编译器默认)和 1(char的大小)的较小值,为1.
由于8是1的整数倍,所以如图所示。
struct S1只有三个成员变量,接下来我们就会用到对齐规则3,结构体的总大小等于所有成员变量中最大对齐数的整数倍。
第一个成员变量的对齐数为1,第二个为4,第三个为1,所以最大对齐数为4。
但现在我们一共占了9个字节,所以不是4的整数倍。
最近的4的整数倍为12,所以该结构体最后的大小为12。
来练个题
struct S2
{
char c1;
char c2;
int i;
};
printf("%d\n", sizeof(struct S2));
参考过程:
参考内存图:
接下来我们来看结构体嵌套的情况,还是从一个题开始
顺便把对齐规则4再回顾一下
struct S3
{
double d;
char c;
int i;
};
printf("%d\n", sizeof(struct S3));
struct S4
{
char c1;
struct S3 s3;
double d;
};
printf("%d\n", sizeof(struct S4));
首先我们先计算struct S3的大小
接下来我们来一步步看 struct S4的大小
- 首先是第一个成员变量,类型为char
- 接下来是关键,根据对齐规则4我们知道。
嵌套的结构体类型对齐自己成员变量中最大对齐数的整数倍。
所以这个时候我们需要知道 struct S3中的最大对齐数。
刚才我们也计算过了,其中最大的对齐数为8。
所以就需要跳过7个字节,然后再放我们的 struct S3类型 - 最后的double是八个字节,跟默认的对齐数8的较小值也是8,由于前面一共占了24个字节,是8的整数倍,所以紧挨着放就行
- 最后我们再检查一下我们占用的字节大小是不是我们最大对齐数的整数倍。
其中,在有嵌套的结构时,内部的结构体代表的最大对齐数是它成员中最大的对齐数。
所以1、8、8中最大值为8,而我们占用的字节数为32 已经是8的倍数了,所以32就为我们的最终答案。
完