C 语言——位域的使用
位域的使用
1. 目的
当需要表示只有“0”和“1”两种情况的开关值时,理论上只需要1个Bit 就能完成任务。但是在编程语言中,最小的数据类型char也是8Bit,当有大量类似上述开关量或者不需要整个8Bit来表示的状态时,程序中定义的多个变量看上去会有些浪费,对于小RAM的单片机来说,能省下来还是比较有意义的。其次,如果能对位直接操作,也使得处理简便多了。
那么问题来了,既然最小数据类型是8Bit,那怎么来表示位变量。
2. 定义
C语言虽然没有提供Bit类型的数据类型,但是提供了一种数据结构,称作“位域”或“位段”,可以在该数据结构中按若干位进行定义。这里主要使用结构题的概念,格式如下
typedef struct{ [TYPE1] name1:lenX; [TYPE2] name2:lenY; [TYPE3] name3:lenZ; }bitSt; bitSt bData; void func1(void) { bData.name1 = 9; bData.name2 = 323; }
以上格式可以看出,定义的大的框架格式为数据结构,内容也是数据类型及名称,但是在名称后面添加了“:len”,且len可以不一样长;
使用和结构体成员的使用是一样的语法:
3. 问题
问题总会来的。
按照定义的数据格式,解析一下数据定义:[TYPE1] name1:lenX;,这表示定义了一个类型为TYPE1,但长度只占其中lenX个bit的位变量name1;
那么问题理所应当就是:位数有没有限制?答案是当然有,这个位数可以随便分配,但是不能超过其数据类型的长度,否则会集到一个报错。
问题2来的会有些慢,或者称为思考2吧,想想sizeof(bitSt)是否和一般的结构题的size是否一样,用下面进阶篇来抛砖引玉一下
4. 进阶
按照以上定义,我们已经定义到三个位变量name1、name2、name3,但是扩展使用位变量将会有更好的作用。例如使用典型的结构体联合体Uion的概念,来将一个已知数据类型进行位拆分:
typedef union { struct { int bitA:1; int bitB:4; int bitC:6; int bitD:9; int bitE:8; int bitF:4; }bits; int val; }bitsInt; void func2(void) { bitsInt bitsI; bitsI.bits.bitA = 2; bitsI.bits.bitB = 3; bitsI.bits.bitC = 9; printf("bitsI.val = %x\n", bitsI.val); }
5. 总结
位域和结构体的区别:位域的定义,类似结构体的定义,但是区别如下:
1. 在变量后面用“:len”来定义所占用的位数
2. sizeof()得出的结果:标准结构体是结构体内部所有变量的总字节的长度(必需考虑字节对齐问题),
但是位域的总长度取决于其中所有变量的总位数的长度,同样要考虑字节对齐问题,由位数最长的那个变量类型为基本单位,总位数小于该长度则为该类型长度,否则以其整数倍补足。
所以定义的位域数据类型的长度,既和数据类型有关,又和总位数长度有关
浙公网安备 33010602011771号