自定义类型 (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定义的位段放在其他平台,那大概率会出错,虽然位段节省了空间,但是存在跨平台的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值