iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言带你学会位段相关知识
  • 406
分享到

C语言带你学会位段相关知识

C语言位段操作C语言位段作用 2023-05-15 05:05:37 406人浏览 八月长安
摘要

目录一、什么是位段二、位段的内存分配三、位段的跨平台问题四、位段的应用五、总结与提炼一、什么是位段 位段的声明和结构是类似的,有两个不同: 位段的成员必须是 int、unsigned

一、什么是位段

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

  1. 位段的成员必须是 intunsigned intsigned int
  2. 位段的成员名后边有一个冒号和一个数字
  • 在下面,我分别写了一个结构体和一个位段,注意看位段的写法和结构体有什么不同
//结构体
struct A {
	int a;
	int b;
	int c;
	int d;
};
//位段
struct B{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

然后我们sizeof去计算一下这个结构体的大小

printf("结构体大小:%d\n", sizeof(struct A));
printf("位段大小:%d\n", sizeof(struct B));

可以看到,结构体的大小是16,位段是8,二者为何会存在区别呢?原因在于这个: 2吗?

  • 那根据位段后面的这些数字,我们可以初步去断定可能大小是这些数组的总和,再转换为字节的。计算一下可以知道为47b,在内存中1B = 8b,要存下这个47个比特位的话应该6个字节就够了,但是结果为什么是8呢?我们不得而知😐

在这里插入图片描述

学习了位段的相关知识后你就知道了

二、位段的内存分配

首先来科普一下位段的相关知识📖

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

那从上面我们就可以提取出一些信息,知道了对于整型而言会开辟出4个字节的数据给到位段作为存放,那接下去呢我们就来分析一下这个位段

  • 仔细观察可以得知每个成员都是整型,那首先开辟出32个比特位
    • _a占了2个比特位,还剩下【30b】
    • _b占了5个比特位,还剩下【25b】
    • _c占了10个比特位,还剩下【15b】
    • _d占了30个比特位,但是剩下的【15b】不够用了,此时编译器会继续开辟出4B,也就是32b的空间来存放

所以最后的结果就是4 + 4 = 8B

struct B{
		//4Byte - 32bit
	int _a : 2;		//30
	int _b : 5;		//25
	int _c : 10;	//15
		//4Byte - 32bit
	int _d : 30;
	//4 + 4 = 8
};

看了我上面的这样计算,你一定会有这些疑问

💬 第一次是32b用剩后的【15b】去哪儿了呢?

💬 _d使用的是【15b】+ 后面开辟出来的32b,还是只用到后面的32b呢?

💬 难道所有平台都是这样吗?有没有不一样的计算方法?

上面是很多同学在课后提出来的疑问,关于这些,你在看完了我下面的分析后就会明白了👇 内存图分析位段分布

接下去我就通过对位段进行分析,然后观察内存分布来揭晓上面究竟是如何计算的。

为了方便期间,这里换一组位段,但是换汤不换药

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

int main(void)
{
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;
	return 0;
}
  • 首先来看一下存放这个位段需要的字节数。可以看到这个位段中的每个成员都是char类型的,所以编译器会首先为其分配一个字节的空间,然后随着变量的存入,最终是需要三个字节

在这里插入图片描述

然后我们来逐一分析一下💻

  • 刚才说了,这个位段在内存中需要开辟三个字节,这些变量要怎么存呢,首先看到变量a占了3个比特位,那是从左边的三位开始放还是右边的三位呢?总不可以从中间开始放吧!

那我们假设一下,从右边往左边放,那么a放完后就是b,占4个比特位,但是放c的时候就放不下了,所以需要在开辟1个字节的空间,此时d再来放的话也放不下了,所以也要再开辟1个字节 ,最后也就需要3个字节的空间

在这里插入图片描述

详细分析如下】:

接下去我们就根据main函数中对位段各变量的初始化,来看看位段在内存中的分布情况:a的初始值为10,不过这是十进制,转换为二进制形式的话就是[1010],转看位段这里a变量的是占了3位,所以会截断成010,将它放到第一个字节处的右边3个比特位处

  • 接下去是b,初始值为12,转换为二进制形式的话就是[1100],而b在内存中也刚好是占4个比特位的大小,刚好第一个字节处还可以放得过,所以继续顺位放置
  • 然后是c,初始值为3,转换为二进制形式的话就是11,但是c在内存中也占5个比特位的大小,所以要在前面做一个扩充便为[00011],但是第一个字节放不下了,上面放了【3】+【4】=【7】,只剩下1个比特位,那我们考虑再开一个字节的空间,为了保持连续性就直接把这个5个比特位的数据放到第二个字节的右边
  • 最后的是d,初始值为4,转换为二进制形式的话就是100,不过d在内存中也占4个比特位的大小,所以要在前面补上一个0,即为[0100],但是第二个字节也放不过了,只剩三个比特位了,所以我们考虑再开一个字节的空间,然后放这个d

上面只是我假设的编译器执行思维,不过真正是怎样的,我们还是要求证一下

  • 那要怎么求证呢?这个很简单,既然这些变量都是存放在位段中,那我们刚才都算出所存放的二进制形式了。对于内存中的地址一般我们看到都是十六进制,所以可以考虑把这些二进制4个为一组转换为十六进制看看
    • 01100010即为——>0x62
    • 00000011即为——>0x03
    • 00000100即为——>0x04
  • 而在内存中左边是低地址,右边是高地址,所以我们看到的应该是62 03 04 cc。来通过【内存】观察一下吧

可以看到,确实和我们分析得是一模一样✌

在这里插入图片描述

看完了上面这个,相信你对一开始的那个位段如何去进行求解的整个流程应该是非常清楚了,留给读者自己的分析观察🔍

三、位段的跨平台问题

接下去我们再来讲讲有关位段的跨平台的问题

  • int 位段被当成有符号数还是无符号数是不确定的
  • 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32)
    • 假设我们将位段中一个变量所占大小设置为30,即占30个比特位,那么它在32为机器上是没问题的,但是放到早期的16位机器上去的话,可能连编译都编不过,因为根本存放不下
  • 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义
    • 刚才我分析的时候假设的是从右往左进行分配,但是呢这在其他平台上可能又是不一样的了
  • 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的
    • 这也就是我们一开始纠结的【15】到底还用不用的问题,这里给出解答,还是不确定,取决于平台

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

  • 这可能还有的老铁不太理解,举个例子:假设结构体A中的这个变量a只可能有【0】【1】【2】【3】这四种取值,那么只需要2个比特位就可以表达这四个数字了,即【00】【01】【10】【11】,那我们便可以使用位段来是实现:2,但若是放在普通结构体中的话就只能是一个整型4个字节32个比特位的大小,这也就浪费了很多的空间
  • 同理,若是变量b也只有5种表示形式的话,5个比特位就够了,cd也是一样。那么这个时候位段就派上用场了,若是使用结构体的话就会浪费掉很多的空间。所以我们前面在看的时候,结构体所占的空间大小是16B,而位段只有8B

在这里插入图片描述

四、位段的应用

清楚了位段的相关知识和使用后,可能还是有同学比较迷惑这个位段到底是用来干嘛的,有什么实际应用场景吗?我们来看看

  • 比方说这里有个IP数据包,有学习过《计算机网络》相关知识的读者应该都很清楚【不了解可以看看网络层知识点汇总】,我们平常在网络上和别人互相聊天的时候,所发送的消息并不是直接在网络链路上进行传送的,而是会将其封装到一个数据包中,它叫做IP数据包,例如我们所发送的呵呵只是里面的一个数据部分,还存在其他很多的字段,这些字段都占有各自的字节数
  • 其实对于这些字节数来说,就是使用【位段】来实现,精准地控制好每个字段需要多少字节数,,就不会造成浪费的现象了

在这里插入图片描述

五、总结与提炼

最后来总结一下本文所学习的内容📖

  • 在本文中,我们首先讲到了位段的相关概念,知道了原来使用结构体还可以实现位段,不过在看了二者的大小后,却产生了疑惑,为什么位段所占的大小是这些呢?
  • 在清楚了位段在内容中的相关分布后,我带着读者一步步分析了位段中的成员数据到底是怎么一个个存放到内存中的,也通过VS中的【内存】验证观察了我们的分析结果,是正确的
  • 然后便说道了位段这个东西其实具备很大的不确定性,因为它存在跨平台的问题,在不同平台下实现的机制可能不同,所以就会导致最后的位段大小会不一致
  • 最后,也说道了位段的作用以及其实际的应用场景,让读者学以致用

到此这篇关于C语言带你学会位段相关知识的文章就介绍到这了,更多相关C语言位段知识内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言带你学会位段相关知识

本文链接: https://www.lsjlt.com/news/208424.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言带你学会位段相关知识
    目录一、什么是位段二、位段的内存分配三、位段的跨平台问题四、位段的应用五、总结与提炼一、什么是位段 位段的声明和结构是类似的,有两个不同: 位段的成员必须是 int、unsigned...
    99+
    2023-05-15
    C语言位段操作 C语言位段作用
  • C语言指针的相关知识点有哪些
    这篇文章将为大家详细讲解有关C语言指针的相关知识点有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。第一站 字符指针----存放字符地址的指针1.使用方法(1)直接使用字符int main()...
    99+
    2023-06-29
  • 一文带你学会C语言中的qsort函数
    目录铺垫知识使用qsort函数进行整型数组的排序使用qsort函数进行浮点型数组的排序使用qsort函数进行结构体数组的排序铺垫知识 qsort函数 参数类型  ...
    99+
    2022-12-21
    C语言 qsort函数 C语言 qsort
  • 一文带你吃透C#中面向对象的相关知识
    目录switch和字典类、成员、方法是时候规范一下写法了继承枚举构造函数和方法重载运算符重载基础必读: 超快速成,零基础快速掌握C#开发中最重要的概念 switch和字典 ...
    99+
    2023-02-26
    C#面向对象知识 C#面向对象
  • 一篇文章带你搞懂Python类的相关知识
    目录一、什么是类二、类的方法三、类的特性四、总结一、什么是类 类(class),作为代码的父亲,可以说它包裹了很多有趣的函数和方法以及变量,下面我们试着简单创建一个吧。 这样就算创...
    99+
    2024-04-02
  • C语言学习基础知识分享
    目录写在前面为何学习C语言语言层面个人层面初识C语言什么是语言标准hellowordmainprintf数据类型byte & bitsizeof常量常量分类变量定义变量变量的...
    99+
    2023-01-28
    c语言入门自学零基础 c语言入门教程 c语言入门基础知识
  • R语言中循环的相关知识详解
    目录repeatwhile向量for循环break和nextrepeat repeat是最存粹的循环,只要不让出来,就一直重复{}中的代码,可以在命令行中输入 repeat{prin...
    99+
    2023-03-19
    R语言 循环使用 R语言 循环
  • R语言中因子相关知识点详解
    因子是用于对数据进行分类并将其存储为级别的数据对象。 它们可以存储字符串和整数。 它们在具有有限数量的唯一值的列中很有用。 像“男性”,“女性”和True,False等。它们在统计建...
    99+
    2024-04-02
  • C语言学习之指针知识总结
    目录一、地址二、指针与指针变量三、指针的作用四、初学指针时常见的错误五、通过调用函数修改主调函数中的值六、指针与一维数组七、使用函数操作一维数组八、指针变量所占字节数九、静态数组的缺...
    99+
    2024-04-02
  • C语言学习之函数知识总结
    目录前言一、引入二、认识函数三、函数的作用四、函数的返回值五、定义函数六、函数的类型七、return语句与break语句的区别八、函数的分类九、主函数十、函数使用举例十一、函数的声明...
    99+
    2024-04-02
  • R语言中循环的相关知识点有哪些
    这篇文章主要介绍“R语言中循环的相关知识点有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“R语言中循环的相关知识点有哪些”文章能帮助大家解决问题。repeatrepeat是最存粹的循环,只要不让...
    99+
    2023-07-05
  • 一篇带你了解C语言--位操作详情
    目录二进制数、位和字节二进制整数有符号整数二进制浮点数介绍八进制和十六进制C按位运算符按位逻辑运算符二进制反码或按位取反:~按位与:&按位或:|按位异或:^用法:掩码用法:打...
    99+
    2024-04-02
  • 不知道该学那一个语言?一文带你了解三门语言
    名字:阿玥的小东东 学习:Python。正在学习c++ 主页:阿玥的小东东 目录 粉丝留言,回答问题 1.首先,初步了解  来源地址:https://blog.csdn.net/m0_64122244/article/detai...
    99+
    2023-09-10
    java 开发语言 python c++
  • C语言基础知识:go是关键字还是标识符?
    标题:C语言基础知识:go是关键字还是标识符? C语言作为一种广泛应用于系统编程和嵌入式开发的高级编程语言,具有严格的语法规则和关键字约定。在C语言中,关键字和标识符是两个非常重要的概...
    99+
    2024-04-02
  • 一篇文章带你了解C语言中volatile关键字
    目录C语言中volatile关键字总结C语言中volatile关键字 volatile关键字是C语言中非常冷门的关键字,因为用到这个关键字的场景并不多。 当不用这个关键字的时候,CP...
    99+
    2024-04-02
  • 谈谈C语言中位运算你要知道的那些事儿
    目录一、概念说明1.概念1.1位运算1.2位运算符2.举例及补充2.1位运算2.2位运算符二、问题实战1.问题描述(开放题)2.输入输出三、源码实现(+详细注释)1.注释版2.纯源码...
    99+
    2024-04-02
  • C语言中你容易忽略的知识点与技巧总结
    目录‍♀️前言字符串常量输出函数puts除法运算的商和余数除法运算的结果有关赋值double类型的运算数据类型和运算总结‍♀️前言 大家有没有一种感觉,随着一门编程语...
    99+
    2024-04-02
  • 关于c语言逗号表达式的运算规则知识点
    逗号表达式是一个有多个子表达式组成的表达式,每个子表达式用逗号分隔。逗号表达式的运算规则如下:1. 逗号表达式从左到右依次计算每个子...
    99+
    2023-08-15
    C语言
  • C语言冷门知识之你可能没听过的柔性数组
    目录一、简述二、具体使用1.用创建柔性数组的方法:2.用普通的写法三、柔性数组的特点一、简述 在c99中有明确的规定允许结构体中最后一个数组大小是未知的。 柔性数组其实是结构体中的最...
    99+
    2024-04-02
  • 你需要知道的关于Go语言和Spring函数的学习笔记
    Go语言和Spring函数是目前非常流行的编程语言和框架,在互联网和移动应用开发领域拥有广泛的应用。如果你想成为一名优秀的开发人员,那么学习这些技术是非常重要的。在本篇文章中,我们将介绍一些关于Go语言和Spring函数的学习笔记,帮助你...
    99+
    2023-08-08
    spring 函数 学习笔记
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作