目录
- 一、位段是什么
- 二、位段的内存分配
- 2.1位段内存分配的原则
- 2.2位段内存分配图解
- 三、位段的跨平台问题
- 四、位段的使用
- 总结
一、位段是什么
位段的声明和结构是类似的,有两个不同
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字。
举例如下:
struct A { int _a:2; int _b:5; int _c:10; int _d:30; };
这个A就是一个位段。
但是结构体可以根据结构体内存对齐确定一个结构体的大小,但是位段的大小怎么确定呢?
位段A的大小是多少呢?
printf("%d\n", sizeof(struct A));
我们利用sizeof操作符来测一下这个A位段的大小是8个字节
但是根据常理来说应该是16个字节呀,我们和结构体对比分析
struct s { int a; int b; int c; int d; }; int main() { printf("%d\n", sizeof(struct s));//16个字节 return 0; }
对比发现位段不是根据他的数据类型来分配内存的。接下来我们看看位段是怎么分配内存的。
二、位段的内存分配
2.1位段内存分配的原则
- 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
- 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
- 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。ps:虽然位段是不跨平台的,但是我们可以根据平台的不同编写不同的代码
struct A { int _a:2; //虽然a是int型但是他所分配的内存根据冒号之后的数字确定,a冒号后面是2,所以他只占用2个比特位 int _b:5; //同理,b成员只需要5个比特位 int _c:10; //10个比特位 int _d:30; //30个比特位 };
那么我们发现这个字段A一共需要47个比特位,好像6个字节就可以完成存储,但是事实并非如此,我们根据位段的内存分配原则,位段的成员是int类型所以按照需要以4个字节的方式开辟,我们先开辟4个字节的空间,即32个比特位,我们可以存储a,b,c但是存储d的时候发现内存不够了,我们再次按照需求再一次开辟4个字节的空间,最终开辟了8个字节的空间而非6个字节的空间来存储位段A。
但是a,b,c存储之后还剩下15个比特位,这些比特位还用不用呢?
答案是不确定的,每个编译器的处理方式都是不一样的,在VS环境下就浪费掉了,位段依旧有很多的不确定性。下面用图例理想表示一下在VS环境下位段的存储:
代码如下:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> struct S { char a : 3; //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; }
2.2位段内存分配图解
假设内存都是由低位向高位使用的,即从右向左使用:
我们将这3个字节的内存中都用0进行初始化:
struct S s = {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> 0 };
三、位段的跨平台问题
int 位段被当成有符号数还是无符号数是不确定的。
int的最高位原本是符号位,但是int位段是有符号数还是无符号数是不确定的。位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。
(16位机器最大可以处理16位数据,寻址空间也只有16位,但是如果传入27位数据就会出问题)
ps:int在16位操作系统下占2个字节。位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
上图只是假设我们从右向左使用,但是分配表示尚未定义,所以也是不确定的。当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
总结:
跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。
牺牲了它的可移植性,但是节省了空间,可以根据需求选择。
为什么说和结构相比,位段可以节省空间呢?
代码如下(示例):
struct A { int _a:2; //虽然a是int型但是他所分配的内存根据冒号之后的数字确定,a冒号后面是2,所以他只占用2个比特位 int _b:5; //同理,b成员只需要5个比特位 int _c:10; //10个比特位 int _d:30; //30个比特位 };
比如这个代码,假设a的取值只可能是0,1,2,3,如果用结构写的话会给a分配4个字节的空间也就是32个比特位,但是a最大需要的比特位是2位,所以会大大造成浪费,并且结构体还存在结构体内存对齐问题,牺牲了空间提高了时间效率。
四、位段的使用
总结
位段的介绍到此结束,总结一下就是位段相比较结构体节省了空间但是失去了可移植性,存在了跨平台的问题,我们可以根据自身的需求来选择是否使用位段,同时位段广泛使用在计算机网络方面,如果想变强就需要学会合理使用位段,加油 少年们!
到此这篇关于C语言快速掌握位段使用的文章就介绍到这了,更多相关C语言位段内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!