1
C语言程序设计
1.9.1.1 8.1.1 位域

8.1.1 位域

计算机语言中的数据通常是以字节为单位表示的。但在实际应用中,常常需要按位来表示信息,如用一位表示一个逻辑变量,用两位表示四种颜色,用若干位表示一种外部设备的各种工作状态。虽然用字节和按位运算符可以实现对这些信息的存储和访问,但C语言为了更有效地解决这类问题,允许定义具有可变长度位的结构成员。这种成员称为位域。它是整型数存储区中相连的位的集合。通过位域可以方便地用成员名访问小于一个字节的存储区。它不仅可以节省存储空间,而且对外部设备工作状态的监控及按位传递信息的处理都是很有用处的。

位域是结构成员的特殊形式,它需要定义位的长度。位域定义的一般形式是:

img635

其中,冒号“:”表示使用的是位域,其后的长度表示需要分配的存储单元的位数。位域变量必须定义为int或unsigned,例如,有下面的结构定义:

img636

img637

这个结构定义了8个成员变量,每个变量只有1位。实际上这8个连续的变量表示了一个字节中的8位。图8.1.1表示了结构变量bits在内存中的分配情况。

img638

图8.1.1 bits在内存中的分配情况

再考虑另一个结构定义:

img639

该结构定义了三个成员变量,其中两个变量只用一位表示,一个变量用连续的两位表示。结构变量der_code可以用来编码一个外部设备的状态信息。内存分配情况是位域变量der_code占用一个字节的低四位,其余位未用。必须注意,位域变量在一个字节中是从左到右分配内存还是从右到左分配内存,与机器的内部结构有关,在不同的机器里,应注意这个问题。

与结构成员的访问方式一样,位域可以用结构成员运算符“.”来访问。若结构是由指针访问的,必须使用箭头运算符。

位域变量有某些限制,比如:不能取一个位域变量的地址;不允许超越整型量边界。例如,下面的定义是非法的:

img640

其中,flagl和flag2的位数超越整型量(16位)的边界。

应该写成:

img641

  }fcode;

这里,第二个成员省略位域变量名,其长度说明为0,表示该位域变量后面定义的位域从下一个“字”边界开始存放。

下面再举一个使用位域的例子。用程序计算一个字符串中每个字符的奇偶校验码,输出该字符及其二进制表示形式。奇偶校验码放在二进制码前面,使奇偶校验码和字符二进制码中“1”的总个数为偶数。

例8-1 使用位域的例子。

程序如下:

img642

  d11100100

  e01100101

  f01100110

程序sp定义为指针变量,它指向位域结构类型struct bit。dp为指向字符指针变量。

  sp=(struct bit*)dp;

是一条关键语句,它表示将dp指向字符串中的某个字符,强行转换成sp指针指向的位域结构类型,使该字符按位域结构类型变量处理。于是通过sp指针可以访问位域结构的成员b0~b6,求出字符二进制位的奇偶校验位,并按序在每一行中显示出字符、奇偶校验位及b0~b6的信息。