当前位置: 首页 > news >正文

【C语言】结构体实现位段

引言

对位段进行介绍,什么是位段,位段如何节省空间,位段的内存分布,位段存在的跨平台问题,及位段的应用。

  158c3f50b199454985017a51dbef9841.png               ✨ 猪巴戒:个人主页✨

               所属专栏:《C语言进阶》

        🎈跟着猪巴戒,一起学习C语言🎈

目录

引言

什么是位段?

位段的作用

位段是如何节省空间?位段的内存分配

位段的内存分配

位段的跨平台问题

        

位段的应用


什么是位段?

位段的声明和结构是类似的,有两个不同:

  1. 位段的成员必须是整形家族的类型
  2. 位段的成员名后面有一个冒号和一个数字。

冒号后面的数字表示的是这个变量将使用多大的内存(单位是比特位)。

int _n : 2 表示的是_n这个整形变量本来是4个字节(也就是32个比特位) ,但是现在要将它的内存缩减到2个比特位。

struct A
{int _n : 2;int _b : 5;int _c : 10;int _d : 30;
};

整形家族的介绍: 

整形类型不仅包括基本整形,还有短整形,长整形,双长整形,字符型和布尔型。

b4fd4b3056ff4971a99486c14624d9ff.png

类型字节数取值范围
int(整形)4

-2147483648~2147483647

short(短整型)2-32768~32767
long(长整型)4/8-2^31~(2^31-1)
long long(双长型)8-2^63~(2^63-1)
char1-2^7~(2^7-1)
bool11,0

         

位段的作用

位段的作用就是节省空间。当我们有一些成员的取值范围有限的时候,所需要的内存空间也不需要太多的空间。

比如说布尔类型

只需要表示真或者假,1表示真,0表示假。实际上布尔类型的变量只占有1个比特位,(1个字节代表着8个比特位),如果使用位段就可以帮助我们节省大量的空间。 

由此,位段所执行的大小不能大于这个变量类型本身的大小,不然就会报错。

546b96377921447d8eb222b0eac7aac5.png

        

位段是如何节省空间?位段的内存分配

下面是刚才给大家做示范的例子,我们现在看这个位段所占用的空间:

#include <stdio.h>
struct A
{int _n : 2;int _b : 5;int _c : 10;int _d : 30;
};
int main()
{printf("%d\n", sizeof(struct A));return 0;
}

9a87e8673b874b9aa753c39567832273.png

 _n,_b,_c,_d这四个变量的大小加在一起,一共是47个比特位,那就是需要6个字节的大小。

但是,我们发现struct A的大小不仅仅是6个字节,而是8个字节

这就说明位段中内存分布不仅仅是简单组合,顺序地一个紧挨着一个地存放。

        

位段的内存分配

  1. 位段的成员可以是整形家族的类型
  2. 位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的
  3. 位段涉及很多不确定因素,位段是不跨平台的,注意可移植的程序应该避免使用位段

2.位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的 

1.例子

下面位段的大小是8个字节

struct A
{int _n : 2;int _b : 5;int _c : 10;int _d : 30;
};

解析struct A的内存分布: 

还是拿这个例子给大家举例:

因为是位段都是int类型,所以这里位段的空间按照4个字节的方式开辟。

首先开辟4个字节来存放内存。

_n是2个比特位,_b是5个比特位,_c是10个比特位,一共是17个比特位

放在4个字节(32个比特位/一个整形大小)当中,剩下15个比特位。

是不足够放下_d(30个比特位),所以另外开辟一个整型大小(4个字节/32个比特位),将_d放进去。

_n,_b,_c放在前面的一个整形,_d放在后面的一个整形。

一共是两个整形,就是8个字节。

db256b441ab74c01b349aa96bcb98916.png

         

  2.例子

下面位段的大小是3个字节

#include <stdio.h>
struct S
{char a : 3;char b : 4;char c : 5;char d : 4;
};
int main()
{printf("%d\n", sizeof(struct S));struct S s = { 0 };s.a = 10;s.b = 12;s.c = 3;s.d = 4;return 0;
}

9160dc1ccd474560bbfe0423b787846a.png

         

 解析struct S位段的内存分布:

这个位段都是char 类型,所以这里位段的空间按照1个字节的方式开辟。

1.首先开辟1个字节(8个比特位),来存放数据

a是3个比特位,b是4个比特位,那么开辟的第一个字节就剩下1个比特位,是不足够存放5个比特位的c变量。

2.开辟下一个字节(8个比特位)存放数据

c是5个比特位,这个字节还剩下3个比特位,不足够存放4个比特位的d变量。

3.开辟下一个空间(8个比特位)存放数据

d是4个比特位,将d存放第三个字节中。

6b12e045b18f47c7bbf0c9e0e04dd112.png

         

 解析struct S的数据在内存中的具体分布:

//在位段中的成员被赋值后,观察内存分布	
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;

struct S在内存中的分布其实是有所差异的,当位段中的成员被赋值后,我们就可以看到位段中的成员是如何分布的。

首先开辟一个字节后,

a=10的二进制数字是01010,位段:3个比特位,所以a的值放入内存中会被裁断,变成010.

b的值是12,位段:4个比特位,所以b存到内存中的值是1100.(数据是以二进制的形式存到内存)

a,b的存放方式如下图:a和b在第一个字节中的排列方式是从右到左的,也就是从高地址向低地址,在一个字节中优先排放高地址。

第二个字节开辟

c=3的二进制数字是11,位段:5个字节,不足5个字节用0来补充高位,也就是00011.

c的存放方式也是在这个字节中优先排放高地址处。

第三个字节开辟

d的值是4,二进制数字是100,位段:4个字节,高位用o来补充,也就是0100

d的存放方式也是在这个字节中优先排放高地址处。

ffe2ba31e0174983abe6ba386abfbb7c.png

所以位段struct S在内存中存放的数据是01100010 00000011 00000100

换算成十六进制数字就是 62 03 04

验证:

通过内存调试,观察内存窗口就可以看到

6ba1d2d19f724c15be105669fe1a14f7.png

         

位段的跨平台问题

  1. int 位段被当成有符号数还是⽆符号数是不确定的。
  2. 位段中最⼤位的数⽬不能确定。(16位机器最⼤16,32位机器最⼤32,写成27,在16位机器会出问题。
  3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
  4. 当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃剩余的位还是利⽤,这是不确定的。

总结: 

跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

        

位段的应用

下图是⽹络协议中,IP数据包的格式,我们可以看到其中很多的属性只需要⼏个bit位就能描述,这⾥使⽤位段,能够实现想要的效果,也节省了空间,这样⽹络传输的数据报⼤⼩也会较⼩⼀些,对⽹络的畅通是有帮助的。
大量的数组经过位段的处理,可以将数据的内存缩小,是数据包的大小变小,数据包变小,网络的传输就会变得快速。
cbbe0daa46a44f1cb28b43085d50b671.png

http://www.lryc.cn/news/258999.html

相关文章:

  • IEEE RAS 机器人最优控制(Model-based Optimization for Robotics)学习资料
  • redis中缓存雪崩,缓存穿透,缓存击穿等
  • C_8练习题答案
  • Web漏洞分析-文件解析及上传(中)
  • 使用Node.js创建接口
  • 【起草】人人都应该有一个chatGPT助手
  • TCP/IP详解——网络基本概念
  • [Linux] ps命令详解
  • QT 中基于 TCP 的网络通信 (备查)
  • 使用MIB builder自定义物联网网关的MIB结构
  • 特权FPGA学习笔记
  • 利用阿里云 DDoS、WAF、CDN 和云防火墙为在线业务赋能
  • Mysql的事务日志
  • 三、Shell 环境
  • 2023年第三届产业数字化【金铲奖】重磅来袭!
  • node.js安装和配置
  • 【周报2023.12.09】
  • 基于ssm大学生创新创业平台项目管理子系统设计与实现论文
  • JS基础之原型原型链
  • 【力扣100】54.螺旋矩阵
  • UI 优先的统一身份认证系统 Casdoor
  • Realme X7 Pro Root 刷机教程
  • postgresql自带指令命令系列三
  • Java_mybatis-结果集映射-ResultTypeResultMap
  • 【Java】MySQL存储 MD5 值应该用 VARCHAR 还是CHAR?
  • pytorch中五种常用随机矩阵构造方法:rand、randn、randn_like、randint、randperm
  • 2023第二届全国大学生数据分析大赛A完整原创论文(含摘要+问题分析+模型建立与求解+python代码)
  • Qt 面试指南
  • 开利网络的数字化技术加持下,加快扶贫和乡村振兴的效果和进程!
  • PR剪辑视频做自媒体添加字幕快速方式(简单好用的pr视频字幕模板)