【详解】C语言冷门知识点之--位段

这篇具有很好参考价值的文章主要介绍了【详解】C语言冷门知识点之--位段。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一, 位段的解释

下面是维基百科对位段的解释:

  位段(或称“位域”,Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作。这种数据结构的好处:

  • 可以使数据单元节省储存空间,当程序需要成千上万个数据单元时,这种方法就显得尤为重要。
  • 位段可以很方便的访问一个整数值的部分内容从而可以简化程序源代码。

  而位域这种数据结构的缺点在于,其内存分配与内存对齐的实现方式依赖于具体的机器和系统,在不同的平台可能有不同的结果,这导致了位段在本质上是不可移植的

二, 位段的声明和使用

  • 虽然位段可以决定用多少位来储存数据,但是切不可认为位段就是可以自定义一个数据类型。位段是依赖结构体来实现的,我们可以认为位段是可以将一个盒子里面格子自定义大小。
    【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++

位段的声明:

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

需要注意的是:

  • 这里面的数字代表的不是字节,是比特(bit)
  • 位段成员的类型只能是整型家族的,例如:int, unsigned int, signed int, char。

位段的使用:

int main()
{
	struct A a;
	a._a = 2;
	a._b = 3;
	a._c = 5;
	a._d = 10;
	return 0;
}

相当于实例化后的a里面的不同大小的内存里放入了数据。

三,位段的空间大小计算

因为不同平台上的规则都是不太一样的,计算出来的结果也会有些许差异,以下使用vs2022的x64环境下运行的
例如:

第一个例子:

#include <stdio.h>
struct A
{
	int _a : 2;//二进制位
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

int main()
{
	printf("%d", sizeof(struct A));
	return 0;
}

上面代码的输出结果是8

  • 声明类型是int类型的,所以一开始先开辟4个字节的内存,也就是32bit。
  • _a用掉了2bit,还剩下30bit。
  • _b用掉了5bit,还剩下25bit。
  • _c用掉了10bit,还剩下15bit。
  • _d需要30bit的空间,但是预先开辟的空间只剩下15bit,所以我们还需要再开辟一个int大小的空间,之前剩下的15bit的空间选择不使用,_d的30bit全放在第二个空间内。
  • 结果为8

第二个例子:

#include <stdio.h>
struct B
{
	int _a : 30;//二进制位
	int _b : 4;
	int _d : 32;
};

int main()
{
	printf("%d", sizeof(struct B));
	return 0;
}
  • 声明类型是int类型的,所以一开始先开辟4个字节的内存,也就是32bit。
  • _a用掉了30bit,还剩下2bit。
  • 由于只剩下2bit,_b需要4bit,所以舍弃2bit,再开辟一个32bit空间, _b用掉了4bit,还剩下28bit。
  • 由于只剩下28bit,_d需要32bit,所以舍弃28bit,再开辟一个32bit空间,_d用掉了32bit
  • 总共开辟了3次int类型的空间,所以结果为12

注意:

  大家有没有发现,我们在声明位段的时候,如果定义的是int,那么冒号后面跟上的数字不能超过32,如果定义的是char,那么冒号后面跟上的数字不能超过8。如果超过以后,就会报出以下错误:
【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++

  其实根据内存对齐原则,如果超出以后,处理器就需要访问两次才能完整的得到数据。所以在定义的时候,应该避免超出应有的内存大小。

四, 位段的内存分配

  • 位段分配的内存中的比特位是从左向右使用的,还是从右向左使用的呢?
  • 如何证明内存分配剩余的比特位不够使用时,是继续使用还是浪费掉呢?

接下来我们分析:
用例代码:

#include <stdio.h>
struct A
{
	char _a : 3;
	char _b : 4;
	char _c : 5;
	char _d : 4;
};
int main()
{
	struct A a = {0};
	a._a = 10;
	a._b = 12;
	a._c = 3;
	a._d = 4;
	return 0;
}

我们假设:位段分配的内存中的比特位是从右向左使用的,分配剩余的比特位不够使用时,浪费掉剩余内存。
则:

  • 我们先定义位段,如下图:
    【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++
  • 执行程序:a._a = 10; 10的二进制为1010,放入_a中,由于_a只有3bit,需要截断,所以舍弃最高位1,放入010:

【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++

  • 执行程序:a._b = 12;,12的二进制为1100,刚好可以放入,如下图:
    【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++
  • 执行程序:a._c = 3;,3的二进制为11,由于_c有5bit,高位添0,放入00011,如下图:
    【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++
  • 执行程序:a._d = 4;,4的二进制为100,放入0100,如下图:
    【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++
  • 程序就基本执行完了,那么内存中是什么样的呢?根据上面分析,我们一开始给结构体初始化为0,我们可以得到:
    【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++
      由于机器是小端存储,所以内存上应该是:62 03 04.
    经过调试,可以看到:
    【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++

  以上也证明了, 在VS2022上,位段分配的内存中的比特位是从右向左使用的,分配剩余的比特位不够使用时,浪费掉剩余内存,重新开辟新的空间。

当然,不同平台得到的结果也可能会不同,这正是位段的缺点,可移植性差,接下来我们看看位段的跨平台问题。

五,位段的跨平台问题

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

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

六, 位段的应用

位段由于跨平台的问题,真正的用途的其中一个是计网的IP数据报:
【详解】C语言冷门知识点之--位段,C语言学习,c语言,开发语言,学习方法,c++

  😄 创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看😄文章来源地址https://www.toymoban.com/news/detail-568178.html

到了这里,关于【详解】C语言冷门知识点之--位段的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c语言位段知识详解

      本篇文章带来 位段 相关知识详细讲解! 如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作的动力之源,让我们一起加油,一起奔跑,让我们顶峰相见!!! 目录 一.什么是位段 二.位段的内存分配  位段的好处 三.位段的跨平台问题 四.位段的应用 位段的声明

    2024年02月15日
    浏览(38)
  • C语言知识点汇总

    C语言知识点保姆级总结,这不得进你的收藏夹吃灰?! 拖了很久的C语言所学知识的简单小结,内容有点多,第一次总结也可能有错误或者不全面,欢迎随时补充说明! ​ 用不同数据类型所定义的变量所占空间大小不一样,定义的变量不是保存于数据类型中,而是因为只有

    2024年01月23日
    浏览(48)
  • [知识点整理]中科院/国科大 自然语言处理nlp 期末考试知识点整理

    本文为2022秋网安学院的自然语言处理课程期末复习知识点整理,水平有限,整理的答案可能有错误或遗漏,欢迎大家指正。 文章的第二部分内容参考了学校学姐的文章,文章写的很好,大家可以关注她: (133条消息) 【一起入门NLP】中科院自然语言处理期末考试*总复习*:考

    2024年02月09日
    浏览(50)
  • 计算机语言知识点梳理

    python是一门强类型、动态型、解释型语言语言 JavaScript是一门弱类型、动态性、解释型语言 typescript是一门强类型、静态型、编译型语言 Java是一门强类型、静态型、编译型语言 变量大小写区分 html css sql java javascript python typescript c 弱类型语言和强类型语言 强类型语言也称为强

    2024年02月09日
    浏览(45)
  • 8086 汇编语言知识点梳理

    机器语言是机器指令的集合 机器指令是一台机器可以正确执行的命令 机器指令由一串二进制数表示 汇编语言的主体是汇编指令 汇编指令是机器指令便于记忆的书写格式 汇编指令是机器指令的 助记符 汇编指令:机器码的助记符,有对应的机器码 伪指令::没有对应的机器

    2024年02月08日
    浏览(50)
  • pgzero所有知识点详解

    目录  什么是pgzero? pgzero的安装 4,正式开始! 1,调整背景色 2,导入角色 3,鼠标事件 5,按键事件 6,刷新功能 1,角色属性 2,功能介绍 7,全局变量and局部变量 1,全局变量与局部变量的区别 2,全局变量如何在功能内使用 8,角色功能及窗口功能 1,角色功能 2,窗口功

    2024年02月05日
    浏览(40)
  • 详解MVCC相关知识点

    前言:学习前,先叙述mysql相关基础知识,一步步了解mysql底层机制。 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted 、Read committed、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。 √: 可能出现    ×: 不会出现

    2024年02月06日
    浏览(41)
  • 【C语言】指针知识点笔记(2)

    目录 一、野指针 二、assert断言 三、指针的使用和传址调用 四、数组名的理解 五、使用指针访问数组

    2024年01月18日
    浏览(42)
  • Spring AOP知识点详解

    Spring AOP是 Spring最核心的能力,那到底什么是AOP呢,今天了不起带大家了解一下。 AOP(Aspect Oriented Programming): 面向切面编程 ,是OOP(面向对象编程)的一个延续,其和OOP一样,也是一种编程思想,不过AOP是一种横向开发模式。 OOP ,面向对象,允许开发者定义纵向的关系,但并适

    2024年02月16日
    浏览(52)
  • 单片机----汇编语言入门知识点

    目录 汇编语句的格式 汇编语句的两个基本语句 子程序的调用 查表程序设计 1.x和y均为单字节数的查表程序设计 2.x为单字节数y为双字节数的查表程序设计 3.x和y均为双字节数的查表程序设计 分支转移程序设计 1.单分支选择结构 2.多分支选择结构 循环程序设计 (1) 计数循环控

    2024年04月28日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包