【C语言】结构体大小的探讨

文章介绍:

 本文主要是介绍结构体在内存中所占用大小的机制,应该是对结构体有一个初步的认识后看。

问题引入:

请看下面代码:

typedef struct S1
{
	int a;
	char b;
	char c;
}S1;

typedef struct S2
{
	char a;
	int b;
	char c;
}S2;

int main()
{
	S1 a;
	S2 b;
	printf("%d", sizeof(a), sizeof(b));
}

请问结果分别是多少?

嗯~~我猜你们都是认为结果是6,毕竟 int 占4个字节,char 占1个字节,将成员都加起来也就6个字节而已嘛,这不简单的很?

如果是这么想,那你就错了,也正好说明了这篇文章值得你一看。
如果想知道的话,那么,请接着往下看吧!

哦,对了,先公布答案吧!
在这里插入图片描述
接下来,我将以这个为例,先给出结构体大小的规则,再一步步分析。

结构体大小的规则:

在讲解规则前,我想先介绍几个名词,它们在规则中起重要作用。

对齐数: 结构体的每一个成员都存在一个对齐数。
对于非结构体成员而言,其对齐数就是其所占内存大小(以字节为单位)。
例如 int 类型的成员其对齐数就是4.
对于结构体成员而言,其对齐数是其成员中的最大对齐数。
例如上面的结构体a,其对齐数是4。
注意:不同的环境其默认对齐数会发生改变。在VS中默认的对齐数为8。

内存图(自己编的,只是方便解释):
从0开始,数字为数位标,可以简单理解是字节数-1。

在这里插入图片描述
下面是具体规则:
1、结构体的第一个成员从内存图的0开始占用。
2、从第二个成员开始,其对齐数具体为本身大小与默认大小的较小值,所占用的内存在第一个成员之后,并且是从其对齐数的倍数为起始位。(这意味着中间内存有可能是空出来的,这一点很重要
3、结构体最后的大小必须是其成员对齐数中最大数的整数倍。

规则其实就这么些,应该也比较好懂,但下面我还是一步步分析。

分析1:

//以这个结构体类型为例
typedef struct S1
{
	int a;
	char b;
	char c;
}S1;

首先是int a:
在这里插入图片描述

然后是char b:
在这里插入图片描述

接着是char c:
在这里插入图片描述

最后:

在这里插入图片描述
分析完一个案例了,简单吧!
但让我们看另一个结构体类型:

typedef struct S2
{
	char a;
	int b;
	char c;
}S2;

首先是char a:
在这里插入图片描述

然后是int b:
在这里插入图片描述

再是char c:
在这里插入图片描述

最后:
在这里插入图片描述
这下你明白了为什么看似一样的结构体可大小却不同了吧!

分析2:

接下来看其中有成员是结构体的情况:

typedef struct Point
{
	char a;
	int b;
}Point;

typedef struct S3
{
	char a;
	Point b;
	double c;
}S3;

int main()
{
	S3 a;
	printf("%d", sizeof(a));
}

请先根据我刚才演示的步骤来推测,应该是很简单的!

在给出自己的答案后来分析吧!
首先是char a:
在这里插入图片描述

然后是Piont b:
在这里插入图片描述

再是double c:
在这里插入图片描述

最后:

在这里插入图片描述
这下子应该是差不多将结构体大小的规则给讲清楚了。

思考题1:像char [ ]这种数组类成员怎么办?

这种其实好办。
以char [ ] 为例。因为其中的每个元素都是char,是以元素的对齐数为准,所以实际的对齐数也是1。

思考题2:为什么要这么设置?

整个规则中最让人摸不着头脑的应该是第二点,这样不是会造成空间浪费么?
对于此似乎没有统一答案,但比较认同的是这应该有“拿空间换时间”的思想。
1、平台问题:
某些平台只能在特定的地址处取某些特定类型的值,否则会报错。(这也是为什么有“对齐数”的说法)
2、性能问题(抢时间):
为了访问未对齐的地址,处理器只能访问两次,而对齐了的地址处理器只需要访问一次。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值