【C语言】位段详解

前言

上一篇文章,我们学习了结构体的相关知识,今天我们来学习和结构体很像的位段
自定义类型:结构体

位段

位:指的是二进制位

位段的声明

位段与结构体的声明有两个不同:

1.位段的成员必须是 int、unsigned int 或signed int 。

成员类型是固定的:char类型也可以,但不要char和int类型混用,类型要保证一致

2.位段的成员名后边有一个冒号和一个数字。

  1. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段

第三点在“位段的不跨平台性”会详细介绍

例子

struct A
{
	int a : 2;
	int b : 3;

};

位段的大小

下面代码的运行结果是什么

struct S
{
	int a : 2;
	int b : 5;
	int c : 10;
	int d : 30;

};

int main()
{
	struct S s;
	printf("%zd\n", sizeof(s));

	return 9;
}

结果:8byte

解释

位,在开始时.提到了,是二进制位(bit位)

我们假设a的范围是0~4,不会更大也不会更小,那么a就不需要用那么大的空间(32个bit位)去存储,它只需要2个bit位就能存储

所以,成员名冒号后面的数字指的就是:用多少个bit位去存储这个成员(数字不能超过类型的最大bit位数)

按照这么算
2+5+10+30 == 48,但结果不对

下面就来介绍位段的内存分配

位段的内存分配

struct S
{
	int a : 2;
	int b : 5;
	int c : 10;
	int d : 30;

};

还是这段代码
我们都知道,int类型是32个bit位
a、b、c共占用了17个bit位,剩下15个bit位,存不下d(30个bit位)
就开辟新的整型空间存储d
所以,总大小就是8个字节

这样就很节省空间了

例题

下面通过这段代码,来讲解一下是如何存储的

struct S {
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

int main()
{
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;

	return 0;
}
开辟空间

根据上面的规则,开辟出三个字节存储a、b、c、d
(如何存储后面会做说明)

在这里插入图片描述

赋值

a是10,二进制表示就是:1010
但a只能存储三个bit位,所以此处存的是010

b是10100,只能存四个bit位,是0100

c是011,c有5个bit位,
不够,那就高位为0

d存储的是0100

所以最终存储的就是:
0010 0010 0000 0011 0000 0100(二进制)
22 03 04 cc cc(十六进制)(后面的没开辟,不用管)

位段不跨平台性

  1. int 位段被当成有符号数还是无符号数是不确定的。
  2. 位段中最大位的数目不能确定。

16位机器最大16,32位机器最大32,当写成27个bit位时,在16位机 器会出问题。

  1. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
  2. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是 舍弃剩余的位还是利用,这是不确定的

位段的应用

在这里插入图片描述

我们在网络上传输信息的时候,需要先将信息进行封装,
上图解释了需要封装进哪些信息,如果使用位段就能很好的存储进每个数据,如果不用位段,那数据包大小就会很大(现阶段,了解即可)

结语

位段的介绍和学习到这里就结束了
下篇文章我们会学习自定义类型中的枚举和共用体
我们下篇文章见~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值