C/C++位域详解整理

位域

一、定义:
有些信息在存储时,并不需要占用一个完整的字节,而只需要占一个或几个二进制位。例如在存放一个开关量时,只有0和1两种状态,只需要用一位二进制位即可。为了节省存储空间,并且为了让处理变得更便捷,C语言又提供了一种数据结构,称为“位域”或者“位段”。所谓位域,就是把一个字节中的二进制位划分为不同的区域,并说明每个区域的位数。每个域都有一个域名,允许程序中按照域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

二、结构:
位域的结构与结构体相似

struct <位域结构名>
{
   ...
   <类型说明符> <位域名> : <位域长度> // 位域列表
   ...
};

ex:

struct Demo
{
 int a : 8;
 int b : 2;
 int c : 4;
};

而位域变量的说明也与结构体变量的说明方式相同,可以采用先定义后说明、同时定义说明、直接说明这三种方式,例如:

方式1:
struct Demo
{
 int a : 8;
 int b : 2;
 int c : 4;
}demo1;

方式2:
struct Demo
{
 int a : 8;
 int b : 2;
 int c : 4;
};
struct Demo demo1;

方式3:
typedef struct Demo
{
 int a : 8;
 int b : 2;
 int c : 4;
}De;
De demo1;

这三种方式中的demo1均为Demo的变量,且占两个字节,其中位域a占8bit,位域b占2bit,位域c占4bit。

三、几点注意事项:

  1. 一个位域必须存储在同一个字节中,不能跨字节存储。如一个字节所剩空间不能存储下一个位域的时候,应从下一个字节开始存储。也可以有意使某个位域从下一单元开始,如:
struct Demo
{
 int a : 4;
 int   : 0;//空域
 int b : 6;//从第二个字节开始存放
};
在这个位域定义中,a占第一个字节的4bit,这个字节的另4bit填0表示不使用,b从第二个字节开始,占4bit。
  1. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说位域的不能超过8bit;

  2. 位域可以无位域名,这时它只用作填充或调整位置。无名的位域是不能使用的。例如:

struct Demo
{
 int a : 4;
 int   : 2; // 这2bit不能使用
 int b : 2;
};

总结:从以上三点来看,位域的本质就是一种结构类型,不过其成员是按二进制位分配的。

四、位域的使用:

位域的使用与结构体相同,其一般形式为:<位域变量名>.<位域名>,位域允许各种格式的输出。

ex:

struct Demo
{
 unsigned int a : 1;
 unsigned int b : 4;
 unsigned int c : 3;
}demo1,*pdemo;

void main()
{
 demo1.a = 1;
 demo1.b = 15;
 demo1.c = 7;
 printf("demo1.a = %d, demo1.b = %d, demo1.c = %d\n",demo1.a,demo1.b,demo1.c);
 
 pdemo = &demo1;
 pdemo->a = 0;
 pdemo->b &= 1;
 pdemo->c |= 3;
 printf("pdemo->a = %d, pdemo->b = %d, pdemo->c = %d\n",pdemo->a,pdemo->b,pdemo->c);
}

上例程序中定义了位域结构Demo,其中有三个位域a,b,c。说明了该位域结构的两个变量demo1和指向Demo类型的指针变量pdemo,这表示位域也是可以使用指针的。
同时也给三个位域进行了赋值(注意赋值不能超过该位域的允许范围)。上例也表示了位域也可以进行复合的位运算。

五、含位域结构体的sizeof

位域结构的成员不能单独被取sizeof值

C99规定int、unsigned int、bool可以做位域的类型,但编译器几乎都对此做了扩展,允许其他类型的存在。

使用位域的主要目的在于压缩内存,大致规则如下:

  1. 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

  2. 如果相邻位域字段的类型相同,且其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

  3. 如果相邻位域字段的类型不同,则各个编译器的具体实现有所差异,VC6不压缩,而Dev C++压缩;

  4. 如果位域字段之间插着非位域字段,则不进行压缩;

  5. 整个位域结构体的总体大小为最宽的基本类型成员大小的整数倍。

ex:

例一:
struct Demo
{
 char c1 : 3;
 char c2 : 4;
 char c3 : 5;
};
sizeof(Demo) = 2;
位域类型为char,第一个字节仅仅能存储下c1和c2,所以c3只能存储到第二个字节中去。

例二:
struct Demo
{
 char  c1 : 3;
 short s2 : 4;
 char  c3 : 5;
};
在VC中: sizeof(Demo) = 6。
因为字节对齐,所以c1要对齐s2,即c1要占用2个Byte,s2要占用2个Byte,而c3占用1个Byte。
又因为整个结构大小最宽的类型为short,所以要是short的整数被,所以还需要填充1个Byte,所以sizeof(Demo) = 6。

在Dev C++中,sizeof(Demo) = 2;

例三:
struct Demo
{
 char c1 : 3;
 char c2;
 char c3 : 5;
};
sizeof(Demo) = 3;
c1占1个bit,c2占1个bit,c3占一个bit。

对作者3w的《C++中的位域详解》这一篇博客进行了整理,以供学习参考
原文链接:《C++中的位域详解》

  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
C语言中的共用体(Union)和位域(Bit-Field)是用来优化内存使用和灵活操作数据的工具。 共用体是一种特殊的数据类型,它允许不同的变量共享同一块内存空间。共用体中的成员变量共享同一内存,占用内存大小等于最大成员的大小。通过修改共用体的一个成员变量的值,可以影响到其他成员变量的值。共用体适用于在不同的数据类型之间进行转换或者存储占用内存大小不定的数据。 位域是一种特殊的结构体成员变量,可以指定成员变量占用的位数,从而实现对内存空间的灵活利用。位域的成员变量必须是整型数据类型,并且位域的大小不能超过该整型类型的大小。位域可以用于减小数据结构占用的内存大小,以及进行数据的位操作。 共用体和位域结构体可以一起使用。通过在位域结构体中定义共用体成员变量,可以实现对内存的灵活使用和数据的高效操作。共用体可以用于存储不同类型的数据,而位域可以用于压缩数据的存储空间。这种结合使用的方式可以为我们的程序带来更加高效和节省内存的特点。 总结起来,C语言中的共用体和位域结构体提供了一种优化内存使用和操作数据的方式。它们可以灵活地对内存空间进行利用,并且能够高效地操作数据。通过合理的使用共用体和位域结构体,我们可以达到节省内存和提高程序执行效率的目的。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值