C语言位段
暴躁小程序猿 人气:1一、位段是什么
位段的声明和结构是类似的,有两个不同
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位,所以会大大造成浪费,并且结构体还存在结构体内存对齐问题,牺牲了空间提高了时间效率。
四、位段的使用
总结
位段的介绍到此结束,总结一下就是位段相比较结构体节省了空间但是失去了可移植性,存在了跨平台的问题,我们可以根据自身的需求来选择是否使用位段,同时位段广泛使用在计算机网络方面,如果想变强就需要学会合理使用位段,加油 少年们!
加载全部内容