结构体内存对齐和结构体实现位段

结构体内存对齐

1.结构体在内存中的存储方式和对齐规则

我们先来看一段代码

struct S
{
	int a;
	char b;
	char c;
};

int main()
{
	printf("%d", sizeof(struct S));
	return 0;
}


我们利用sizeof去计算了一下struct S这个结构体的大小发现是8个字节,但是我们结构体中只存了int,char,char六个字节就足以存放这三个类型的元素为什么会申请到八个字节呢?
我们在这里就得提到一个名词叫做结构体内存对齐,什么叫做结构体内存对齐呢?
在此之前我们又得引入一个偏移量的概念偏移量顾名思义就是:偏移了多大的字节我们可以用offsetof这个“宏"不清楚的可以去这里看offsetof的详细使用方法
在这里插入图片描述
我们可以发现他的偏移量分别为0,4,5通过画图在这里插入图片描述
可以看见大致在内存中是以这种方式存储的a,b,c三个变量但为什么最终还是浪费了两个字节的内容呢?

我们来了解结构体的对齐规则:
1.结构体中的首个成员变量必须放在偏移量为0的地方
2.从第二个成员变量开始,每个成员必须放在其对齐数的整数倍数上
对齐数的计算方法:结构体中成员变量的自身大小和编译器的默认对齐数大小选取其中的较小值(vs的默认对齐数是8但是也有编译器无默认对齐数那就取其成员变量自身的大小作为对齐数)
3.结构体的总大小必须是其成员变量中最大对齐数的整数倍
4.当存在结构体嵌套的时候,比如说A结构体中包含了结构体B,那么B的对齐数是B中所有成员变量的最大对齐数用作B的对齐数,其A的结构体大小还是按照第三条计算

以上就是计算结构体大小的四条规则
我们再来看刚刚的代码是如何对齐的
在这里插入图片描述
当然我们可以去修改默认对齐数利用#pragma pack(x)这个x就是你想要设置的默认对齐数,当我们修改至合理的默认的对齐数的时候我们可以节省我们的空间

2.为什么要有结构体内存对齐

我们现在用的设备多是32位或64位机器,我们以32位的机器为例,CPU
一次只能访问32个bit位的空间即四个字节的空间,如果我们是连续存放的时候如:
在这里插入图片描述
我们会发现这里的CPU使用了两次
但是当我们对齐的时候
在这里插入图片描述
这里的CPU只使用了一次,所以我们采用对齐的方式去存储就是通过牺牲空间来换取时间上的便利

用结构体实现位段

1.什么是位段

位段位段,这里的位就是指二进制位所以想用位段的前提是这个变量必须属于整形家族即(char,short,int,long…),它是通过结构体的方式去实现的其写法如图:
在这里插入图片描述

写法就是成员变量+:数字因为我们有时候不需要那么大的空间就可以存放我们想要存放的数据所以产生了位段这个概念,我们发现这里就只使用了两个字节而并非开辟了三个字节大小的空间,那它是怎么实现的呢?
在这里插入图片描述
这就是位段存放的实现

2.位段的利弊

利:位段可以帮我们节省空间,因为结构体能做到的使用位段也大致都可以只要你知道你需要的内存大小
弊端:不可以跨平台使用,因为C语言对待位段的定义不够明确,所以每种编译器在处理位段和结构体大小的时候会有所差异,所以当我们要写跨平台项目的时候不推荐使用位段
且int 位段被当成有符号还是无符号的数也不确定
位段中最大位也不确定就是到底是32位机器还是64位机器,不同的机器也会有差别,所以跨平台问题严重,希望各位好好辨别,谨慎使用位段!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老幺*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值