三分钟让你学会使用位段

三分钟学会使用位段

位段知识点集合

在这里插入图片描述


前言

  位段位段的声明和结构是类似的,但是也会有所不同,此篇文章将带你了解位段是什么已以及位段的使用和位段的特性。


一、位段是什么?

位段的声明和结构是类似的,有两个不同
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 = {
    
     0 };

在这里插入图片描述

三、位段的跨平台问题

  1. int 位段被当成有符号数还是无符号数是不确定的。
    int的最高位原本是符号位,但是int位段是有符号数还是无符号数是不确定的。
  2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。
    (16位机器最大可以处理16位数据,寻址空间也只有16位,但是如果传入27位数据就会出问题)
    ps:int在16位操作系统下占2个字节。
  3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
    上图只是假设我们从右向左使用,但是分配表示尚未定义,所以也是不确定的。
  4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
    总结:
      跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。
      牺牲了它的可移植性,但是节省了空间,可以根据需求选择。
      为什么说和结构相比,位段可以节省空间呢?
    代码如下(示例):
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位,所以会大大造成浪费,并且结构体还存在结构体内存对齐问题,牺牲了空间提高了时间效率。

四、位段的使用

在这里插入图片描述


总结

  位段的介绍到此结束,总结一下就是位段相比较结构体节省了空间但是失去了可移植性,存在了跨平台的问题,我们可以根据自身的需求来选择是否使用位段,同时位段广泛使用在计算机网络方面,如果想变强就需要学会合理使用位段,加油 少年们!
  如果这篇文章对你有帮助可以关注加三连,后续会持续分享自己学习过程中的收获,也欢迎大家私信我互相交流,小程序猿在此拜谢各位大佬!

猜你喜欢

转载自blog.csdn.net/MDLYB/article/details/126949959