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

目录

一、位段的定义

二、位段的声明

三、位段的内存分配

四、位段在内存中的存储方式

五、位段的优点

六、位段的跨平台问题

七、位段的应用

八、位段使用的注意事项


一、位段的定义

信息的存取一般以字节为单位。实际上,有时存储一个信息不必用一个或多个字节。

例如:"真"或"假"可以用0或1表示,只需1位即可。这时我们就可以用位段来进行存储。

那么什么是位段呢?

        位段(Bit Field)是C语言中的一种数据结构,它允许程序员在一个结构体中以位为单位来指定其成员所占的内存长度。这种以位为单位的成员称为"位段""位域"

        位段的定义要借助于结构体,即以二进制位为单位定义结构体成员所占存储空间,从而可以按"位"来访问结构体中的成员。

        位段与结构体形式与用法上是很相近的,但位段可以用来描述更为细腻的数据级别。

二、位段的声明

位段的声明语法形式如下:

struct   标签

{

    位段成员类型 位段成员名:分配内存的大小;

}

举例:

struct A
{int _a : 2;  //分配2bit的空间大小int _b : 5;	 int _c : 10;int _d : 30;
};
//A就是一个位段类型
//int:位段的成员类型   _a: 位段成员名   2:分配内存的大小 

注意:

  1. 位段的成员必须是(整型):int,unsigned int 或signed int,char
  2. 位段的成员名后边有一个冒号和一个数字
  3. 位段成员名中的 "_" 是可以是可以省略的,加上下划线与不加都可以,只是一种命名风格。
  4. 位段中分配内存的大小,宽度必须小于等于指定类型的位宽度。(即:冒号后面的数字的bit不能超过前面类型所占的bit
  5. 位段的位指的是二进制位
  6. 位段的声明应在结构体/联合体中。

    原因:

    位段是依赖结构体/联合体来实现的。在位段的声明和使用中,虽然可以决定用多少位来存储数据,但不能认为位段就是可以自定义的数据类型。可以理解为:位段是依赖于结构体实现的自定义类型。可以认为位段是将一个盒子里面的格子自定义大小。

三、位段的内存分配

位段所占内存大小为多少呢?

我们测试下面一段代码:

struct S
{char _a : 3;char _b : 4;char _c : 5;char _d : 4;
};int main()
{printf("%d\n", sizeof(struct S));return 0;
}

测试结果如图所示:

为什么会是3个字节(byte)呢?

原因:

  1. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  2. 一个位段必须存储在同一存储单元(即字)之中,不能跨两个单元。如果其单元空间不够,则剩余空间不用,从下一个单元起存放该位段。

四、位段在内存中的存储方式

我们看如下一段代码:

#include <stdio.h>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;
}

调试结果如下:

我们调试发现:

10,12,3,4在内存中是以16进制存放,为什么是62 03 04呢?

分析如下:

可知:位段中的成员在内存中是从右向左分配。

注意:

  1. 大小端指的是如果一个数据存储时超过一个字节的时候,才有字节顺序。这里是一个字节(内部),所以不谈顺序。
  2. 这里是先开辟一个字节,再开辟一个字节,最后再开辟一个字节,所以存放顺序一定是如图所示的存放方式。

五、位段的优点

 可以使数据单元节省储存空间,避免不必要的空间浪费。

 但是所谓节省空间是在一定程度上节省空间,并不是完全不浪费。

六、位段的跨平台问题

        1、int被位段作为是:无符号整数还是有符号整数,这个并没有做出明确的规定。

        2、位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器就会出现问题)

        3、位段中的成员在内存中是从左向右分配,还是从右向左分配尚未定义。(vs中是从右向左)

        4、当一个结构包含两个位段,假设第二个位段成员无法全部容纳于第一个剩余的位时,是把一个空间填满再放到新开辟的空间,还是直接全部放到新的空间,这个没有明确的规定。(vs中是直接全部放到新的空间)

补充:

  • 只有在位段的时候,int是没有确定是使用unsigned还是signed。除此之外int都是signed int。
  •  而char才是在使用和不使用位段的时候都是不确定的。

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

七、位段的应用

        1、在一些特定的应用场景中,需要对一个整数类型的变量中的每一位进行单独的控制或访问。例如,硬件寄存器常包含一些特定的位用于表示设备的状态,配置选项或标志位。使用位段可以让程序员更方便地访问和控制这些位,不需要进行位运算。

        2、在网络协议中,IP数据报的格式。可以看到其中很多属性只需要几个bit位就能描述,使用位段就能够实现想要的效果,也节省了空间,这样网络传输的数据报大小也会较小一些,对网络的畅通是有帮助的。

八、位段使用的注意事项

1、位段无地址,不能对位段进行取地址运算。

原因:

位段的几个成员共用一个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位置处是没有地址的。

因为内存中是每个字节分配一个地址,一个字节内部的bit位是没有地址的。

所以不能对位段的成员使用&操作符,这样就不能使用scanf直接对位段的成员输入值,只能是先输入一个值存放在一个变量中,然后再赋值给位段的成员。

如下所示:

#include <stdio.h>struct A
{int _a : 2;int _b : 5;int _c : 10;int _d : 30;
};int main()
{struct A sa = { 0 };scanf("%d", &sa._b); //这是错误的//正确的示范int b = 0;scanf("%d", &b);sa._b = b;return 0;
}

2、位段里的成员类型要尽量保持一致。否则会带来没必要麻烦,它内存开辟的时候可能会跟期望的不一样。

原因:

位段使用的场景本来就非常苛刻。如果再类型不一样,这样写出来的代码可控性就会变得差,而且它有许多不确定性,导致了它的不跨平台性。

3、位段在访问时与结构体访问方式相同,通过点操作(.)进行访问。访问时注意不要超出了所定义的位段大小。

4、两位段相邻时,相同数据类型的位段在编译过程中可以提高存储效率,而不同数据类型的位段则更可能需要考虑数据对齐而降低存储效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/21541.shtml

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

相关文章

匠心独运,B 端系统 UI 演绎华章之美

匠心独运&#xff0c;B 端系统 UI 演绎华章之美

上位机图像处理和嵌入式模块部署(f103 mcu获取唯一id)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于stm32f103系列mcu来说&#xff0c;一般每一颗原厂的mcu&#xff0c;都会对应一个唯一的id。那这个id可以用来做什么用呢&#xff1f;个人认为&…

PX4 ROS2 真机

如果仿真跑通了。 真机遇到问题&#xff0c;可参考此文章。 ubuntu22 px4 1.14.3 ros2 humble 硬件接线。 先找两个usb - ttl串口&#xff0c;分别接到两台主机上&#xff0c;保证串口通信正常。 图中是个六合一的。浪费一天时间&#xff0c;发现是串口设置错误&#xff…

力扣 101. 对称二叉树

给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool check(struct TreeNode* L,struct TreeNode* R){if(!L&…

socket网络编程——套接字地址结构

一、通用 socket 地址结构 socket 网络编程接口中表示 socket 地址的是结构体 sockaddr&#xff0c;其定义如下&#xff1a; 1. #include <bits/socket.h> 2. 3. struct sockaddr 4. { 5. sa_family_t sa_family; 6. char sa_data[14]; 7. }; sa_family 成员是地址族类型…

【云原生】kubernetes中pod的生命周期、探测钩子的实战应用案例解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

强国机械制造有限公司引入先进制造技术,提升产品质量和生产效率

强国机械制造有限公司2024年6月3日宣布引入了一系列先进制造技术,包括机器学习、人工智能和物联网等,旨在提升其产品的质量和生产效率。这些前沿技术的应用,使得公司的制造过程更加智能化和数据驱动,显著提高了产品的精度和稳定性。 通过机器学习算法,强国机械能够分析和预测生…

《深入浅出C语言:从基础到指针的全面指南》

1. 简介 C语言是一种通用的编程语言&#xff0c;广泛应用于系统编程、嵌入式系统和高性能应用程序。它由Dennis Ritchie在1972年开发&#xff0c;并且至今仍然非常流行。C语言以其高效、灵活和强大的功能著称&#xff0c;是许多现代编程语言的基础。 2. 基本语法 2.1 Hello, …

VIKOR方法

简介 VIKOR方法是一种多标准决策&#xff08;MCDM&#xff09;或多标准决策分析方法。它最初由 Serafim Opricovic 开发&#xff0c;用于解决具有冲突和不可通约&#xff08;不同单位&#xff09;标准的决策问题&#xff0c;假设冲突解决可以接受妥协&#xff0c;决策者想要一…

C++中static关键字用法总结

在C中&#xff0c;关键字static有多种用途&#xff0c;它可以用于变量、函数。下面是static在不同上下文中的作用和举例。下面从static修饰的变量、函数三方面进行总结。 1、静态变量 静态变量分为全局变量、局部变量、函数中变量两种。 1.1 静态全局变量 静态全局变量声明在…

前端框架前置知识之Node.js:Node.js入门

前端程序员有必要学 Node.js 吗&#xff1f;要学到什么程度&#xff1f; 小朋友&#xff0c;你是否有很多问号&#xff1f; 对于node.js&#xff0c;不知道你是否和我一样有很多问号&#xff1f; 其实在学习node.js之前&#xff0c;我已经学完了Vue框架&#xff0c;而且已经…

排序算法(C++)

参考C算法&#xff0c;这里面有些写法也值得商榷。 1. 冒泡排序算法 冒泡排序算法代码和思路比较简单&#xff0c;大家如果在面试时被要求实现排序时&#xff0c;可以用这种方法来实现。 该算法里&#xff0c;会统一地遍历待排序的数据&#xff0c;每次比较两个相邻的数据&a…

变现 5w+,一个被严重低估的 AI 蓝海赛道,居然用这个免费的AI绘画工具就能做!

大家好&#xff0c;我是画画的小强&#xff0c;致力于分享各类的 AI 工具&#xff0c;包括 AI 绘画工具、AI 视频工具、AI 写作工具等等。 但单纯地为了学而学&#xff0c;是没有任何意义的。 这些 AI 工具&#xff0c;学会了&#xff0c;用起来&#xff0c;才能发挥出他们的…

深入探讨ChatGPT API中的Tokens计算方式和计算库

引言 在现代人工智能应用中&#xff0c;自然语言处理&#xff08;NLP&#xff09;技术无疑是最受关注的领域之一。OpenAI推出的ChatGPT&#xff0c;作为一种先进的对话模型&#xff0c;已经在多个领域展示了其强大的语言生成能力。为了更好地使用ChatGPT API&#xff0c;理解其…

Amazon云计算AWS(二)

目录 三、简单存储服务S3&#xff08;一&#xff09;S3的基本概念和操作&#xff08;二&#xff09;S3的数据一致性模型&#xff08;三&#xff09;S3的安全措施 四、非关系型数据库服务SimpleDB和DynamoDB&#xff08;一&#xff09;非关系型数据库与传统关系数据库的比较&…

短剧出海的优势分析

海外短剧作为一种新兴的内容形式&#xff0c;正以其独特的魅力迅速占领市场&#xff0c;为企业带来了前所未有的商业机遇。本文将深入探讨短剧出海的优势&#xff0c;并为企业和老板们提供实用的操作指南。短剧出海是一个包含多个步骤的复杂过程&#xff0c;短剧出海需要综合考…

山景BP1048固件加密

1.在电脑的USB口插入山景公司的加密狗。 2.打开MVAssistant_BP10xx_V1.8.15(2022.04.19)软件 3.选择芯片型号。 4.选择M4模式 5.code数据选择编译好的固件&#xff0c;const数据选择编译好的提示音 6.输入加密密码 7.点击代码加密 8.导出MVA文件

强化学习 (三) 动态规划

文章目录 迭代法网友认为的迭代策略评估与价值迭代的区别 迭代策略评估的进一步解释附录 传统dp作用有限&#xff1a; 需要完备的环境模型计算的复杂度极高 其它方法都是对dp的近似&#xff0c;近似的出发点是解决上面两个问题。 有一种说法是&#xff0c;强化学习其实就是拟…

PS系统教程09

修复照片 修饰工具 污点修复画笔工具&#xff08;J&#xff09; 主要作用&#xff1a;去除一些污点或者不需要的 【&#xff1a;缩小】&#xff1a;放大 目标&#xff1a;去掉这两个点 修复画笔工具 也就是说我们要有取样点 选择修复画笔工具按住Alt键吸取周边相近颜色松开单机…

导航时间与坐标转换

前言&#xff1a; 该章节代码均在Gitee中开源&#xff1a;因为这章是学校作业&#xff0c;所以稍微正经点. 时空位置转换https://gitee.com/Ehundred/navigation-engineering/tree/master/%E5%8D%AB%E6%98%9F%E5%AF%BC%E8%88%AA%E5%8E%9F%E7%90%86/%E5%AF%BC%E8%88%AA%E6%97…