自定义类型 (2) 结构体详解(位段)

本文深入讲解位段的声明与存储方式,通过实例演示如何利用位段节省内存空间,并讨论位段在不同平台上的表现差异及潜在风险。

在上一篇博客中,我们介绍了结构体以空间换时间的做法:内存对齐,在这篇博客中,将会介绍结构体节省空间的方法:位段


请添加图片描述

🚩1.位段的声明以及存储

位段的声明与结构体的声明相似,但又有所不同

typedef struct student
{
	char a : 2;
	char b : 5;
	int c : 5;
}student;

可以看到,位段的声明和普通结构体变量的声明的区别是,成员变量的声明后有一个 : 还有一个数字,这是什么意思呢?其实是代表占几个字节,再解释一下就是,char a,先开辟了一个一个字节的空间,然后把其中的三个位,给a,然后再往下看,char b:5,再把上次没用完的空间给b,判断一下,够五个,给b,不够就再建一个新的字节,然后int c:5,由于c和a,b占的字节大小都不一样,所以他单独开辟一个空间,并把其中的五个位给c,如果把空间用二进制表示画图表示如下:
在这里插入图片描述

假定一个圈代表一位,那么内存表示就是这样的,可以看到,a和b同处于一个字节当中,这就是位段的好处了,可以节省空间,下面我们看一个例子:

typedef struct student
{
	char a : 2;
	long b : 5;
	int c : 5;
}student;
int main()
{
	student a = { 1,18,1 };
	return 0;
}

经过这样的赋值以后,我们先按照之前的思路分析一下其在内存中是如何存储的:
先开辟了一个字节的空间,然后分给a一个位,然后转向long b,因为字节对齐,所以b从偏移量为4的地址处开辟空间,然后把其中五位给b,再转向int c,由于int 和long是同大小的变量,所以把a没用完的位分给c五个,并赋值。
现在看看内存中的存储情况
在这里插入图片描述
在这里注意几个点:
1.vs是小端字节序,也就是低地址存低位
2.位段的空间是从低地址开始给的
3.位段中也出现了和内存对齐相仿的对齐现象(在不同大小的成员变量之间存在)。

我们明明存的是 1,18,1为什么内存中存储的是32呢?,我们把18先用二进制表示 0001 0010,要注意在这段空间中只有五个是属于b的也就是 10010剩下的空间是给下一个成员变量的,下一个成员变量的值是1,从上一个变量剩下的空间开始赋值 那也就是 0011 0010 再用16进制表示那就是32了。
通过这样的例子,大家应该初步了解位段是个什么东西了,但是还有一些注意的点,在这里总结一下:

📍注意!

1.位段的成员必须属于整型家族的类型
2.如果上一个成员变量所处的空间的剩余不足以支撑下一个成员变量,那将会开辟新的空间
3.你给成员多少个位,那成员就只能使用多少个位,超出的部分会截断(保留低位)
4.位段虽然能节省空间,但是有很多不确定因素,跨平台很危险,通用性,可移植程序应该避免使用位段

📍位段的跨平台问题(不确定因素)

1.int 是无符号数还是有符号数这是不确定的
2.平台使用的是大端字节序还是小端字节序这是无法确定的
3.对于不足以支撑下一个成员开辟的空间,是舍弃还是利用,这是无法确定的

在这里解释一下第二点,其实意思就是vs采用的是小端字节序,低地址存低位,所以分配空间时是从左往右分配,但要是其他大端平台,那就是低地址存高位,我还想从低位开始分配的话,那就是从右往左开始分配。举个例子:

typedef struct student
{
	char a : 2;
	long b : 5;
	int c : 5;
}student;
int main()
{
	student a = { 1,18,1 };
	return 0;
}

还是这样的一个位段,给b分配空间的时候,b是 0001 0010,a分配以后是 0011 0010,这是没有问题的,但是这是一个四个字节的空间,完整表示是
0000 0000 0000 0000 0000 0000 0011 0010
经过vs编译以后存放的顺序是 32 00 00 00
但是要是经过大端平台就是 00 00 00 32 ,所以你要是把vs定义的位段放在其他平台,那大概率会出错,虽然位段节省了空间,但是存在跨平台的问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值