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

news2024/10/7 17:17:51

引言

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

  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.coloradmin.cn/o/1305675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣每日一题----2008. 出租车的最大盈利

这题我们是怎么思考的呢&#xff1f; 已知有乘客最多30000个&#xff0c;有最多100000个地点&#xff0c;那么通过算法时间复杂度&#xff0c;不可能是O(n^2), 那么我们就可以去看题目&#xff0c;题目又是最多盈利多少元&#xff1f;那么很容易联想到动态规划&#xff0c;并…

9:00面试,9:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到12月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40…

支持向量机模型(超详细,含案例代码)

什么是支持向量机&#xff1f; 支持向量机&#xff08;Support Vector Machine&#xff0c;SVM&#xff09;是一种在机器学习领域中用于分类和回归分析的强大算法。它是一种监督学习算法&#xff0c;其目标是在特征空间中找到一个超平面&#xff0c;将不同类别的数据点分开&…

Axure元件的介绍使用与登录界面以及个人简历的绘制

目录 一.Axure元件介绍 1.1.简介 1.2.常见的元件 1.3.元件的操作 二.基本元件的使用 2.1.矩形和圆形 2.2.图片 2.3.文本元件 2.4.热区 2.5.线段元件 三.表单型元件的使用 3.1.文本框 3.2.文本域 3.3.下拉列表 3.4.列表框 3.5.单选按钮 3.6.复选框 四.菜单和表…

2007-2022年全国各省数字经济政策支持力度、ZF工作报告数据经济词频数据

2007-2022年全国各省数字经济政策支持力度、ZF工作报告数据经济词频数据, 1、时间&#xff1a;2007-2022年 2、范围&#xff1a;31省市 3、指标&#xff1a;行政区划代码、年份、地区、所属地域、文本总长度、仅中英文-文本总长度、文本总词频-全模式、文本总词频-精确模式、…

dockerfile基于NMP+wordpress创建镜像

内部通信地址 nginx 172.111.0.10 docker-nginx mysql 172.111.0.20 docker-mysql php 172.111.0.30 docker-php 1、创建单独目录 2、创建容器的自定义网络 docker network create --subnet172.111.0.0/16 --opt "com.docker.network.bridge.name"&quo…

19、命令模式(Command Pattern,不常用)

命令模式&#xff0c;将一个请求封装为一个对象&#xff08;命令&#xff09;&#xff0c;使发出请求的责任和执行请求的责任分割开&#xff0c;有效降低系统的耦合度。这样两者之间通过命令对象进行沟通&#xff0c;这样方便将命令对象进行储存、传递、调用、增加与管理。命令…

磁力计LIS2MDL开发(1)----轮询获取磁力计数据

磁力计LIS2MDL开发.1--轮询获取磁力计数据 概述视频教学样品申请源码下载通信模式速率生成STM32CUBEMX串口配置IIC配置CS设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置设置速率启用偏移消除开启温度补偿设置为连续模式轮询读取数据主程序演示 概述 本文将介绍如何使…

明道云在戴斯克,从业务整合到高效管理的秘诀

内容来自演讲&#xff1a;付震东 | 北京戴斯克商务有限公司 &#xff5c;数字化负责人 摘要 本文介绍了明道云在戴斯克公司的应用以及数字化转型过程中所起的作用。戴斯克公司使用明道云后&#xff0c;实现了系统落地速度、工作效率、决策方法和工作意识的提升。通过不断抽象…

集成开发之如何用好明道云

内容来自演讲&#xff1a;张嵩 | 苏州睿能科技有限公司 | 公司负责人 摘要 这篇文章介绍了作者所在公司如何利用明道云进行集成开发&#xff0c;并分享了四个实际案例。在第一个数字化实验室项目中&#xff0c;该公司使用明道云取代现有的STARLIMS商业软件&#xff0c;并实现…

微表情检测(四)----SL-Swin

SL-Swin: A Transformer-Based Deep Learning Approach for Macro- and Micro-Expression Spotting on Small-Size Expression Datasets 在本文中&#xff0c;我们致力于解决从视频中检测面部宏观和微观表情的问题&#xff0c;并通过使用深度学习方法分析光流特征提出了引人注…

XGBoost和LightGBM时间序列预测对比(备忘)

XGBoost和LightGBM都是目前非常流行的基于决策树的机器学习模型&#xff0c;它们都有着高效的性能表现&#xff0c;但是在某些情况下&#xff0c;它们也有着不同的特点。 XGBoost和LightGBM简单对比 训练速度 LightGBM相较于xgboost在训练速度方面有明显的优势。这是因为Ligh…

【Spring教程26】Spring框架实战:从零开始学习SpringMVC 之 bean加载控制

目录 1 问题分析2 思路分析3 环境准备4 设置bean加载控制5 知识点1&#xff1a;ComponentScan 欢迎大家回到《Java教程之Spring30天快速入门》&#xff0c;本教程所有示例均基于Maven实现&#xff0c;如果您对Maven还很陌生&#xff0c;请移步本人的博文《如何在windows11下安装…

智能优化算法应用:基于哈里斯鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于哈里斯鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于哈里斯鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.哈里斯鹰算法4.实验参数设定5.算法结果6.…

【尘缘送书第七期】2023年度盘点:智能汽车 | 自动驾驶 | 车联网

【文末送书】今天推荐几本智能汽车 | 自动驾驶 | 车联网领域优质书籍。 目录 引言1 《智能汽车》2 《SoC底层软件低功耗系统设计与实现》3 《SoC设计指南》4 《蜂窝车联网与网联自动驾驶》5 《智能汽车网络安全权威指南&#xff08;上册&#xff09;》6 《智能汽车网络安全权威…

Keil 编译输出信息分析:Program size: Code, RO-data , RW-data, ZI-data

一般 MCU 包含的存储空间有&#xff1a;片内 Flash 与片内 RAM&#xff0c;RAM 相当于内存&#xff0c;Flash 相当于硬盘。编译器会将一个程序分类为好几个部分&#xff0c;分别存储在 MCU 不同的存储区。 如图所示&#xff0c;在Keil中编译工程成功后&#xff0c;在下面的Bul…

智能优化算法应用:基于闪电搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于闪电搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于闪电搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.闪电搜索算法4.实验参数设定5.算法结果6.…

NCNN 源码学习【二】:模型加载

​ 正文 这次先来看一段NCNN应用代码中&#xff0c;最先出现的部分&#xff0c;模型加载 ncnn::Net squeezenet; squeezenet.load_param("squeezenet_v1.1.param"); squeezenet.load_model("squeezenet_v1.1.bin");首先我们可以看到一个 ncnn的类Net&am…

【@Cacheable的使用,及设置过期时间 配置方式】

Cacheable的使用&#xff0c;及设置过期时间 配置方式 使用方式 使用方式 Cacheable(cacheNames “ssss#30” ,key “#aaa‘‘#beginTime’’#endTime”) cacheNames/value &#xff1a;用来指定缓存组件的名字key &#xff1a;缓存数据时使用的 key&#xff0c;可以用它来指…

【Oracle】backup备份时报错ORA-19809,ORA-9804

Oracle备份数据库时报错 ORA-19809: limit exceeded for recovery files ORA-19804: cannot reclaim 10305536 bytes disk space from 4385144832 limit 1.清理过时的备份&#xff1a; 使用RMAN删除不再需要的过时备份&#xff0c;以释放空间。执行以下命令&#xff1a; DEL…