C语言快速掌握位段使用

 

一、位段是什么

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

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位段内存分配的原则

  1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
  2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。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语言位段内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 1.前言大家在学习C++的时候一定会学到STL(标准模板库),这是C++标准库中最重要的组成部分,它包含了常用的数据结构和算法。今天呢,我们首先来学习STL中的vector容器 2 ...