9.1.11 位域
1. 什么叫位域
有些信息在存储时,并不需要占用一个完整的字节,而只需占一个或几个二进制位。例如,在存放一个开关量时,只有0和1 两种状态,用一个二进制位表示即可。而在使用C语言开发程序,特别是一些系统级或嵌入式程序时,内存往往是特别宝贵的。为了节省存储空间,并使处理简便,C语言提供了一种数据结构,称为“位域”或“位段”。
所谓“位域”是把一个字节中的二进制位划分为几个不同的区域,并说明每个区域的位数。每个区域有一个域名,允许在程序中按域名进行操作。这样一个字节的二进制位就可以表示几个不同的量。
这有点类似于时下流行的两截裤,如果把一整条裤子看作一个字节,两截裤就是把一条裤子分成两截,而位域则是把一个字节分成几截,每截独立的表示一个量。如图9.12所示:
图9.12 两截裤与位域
2. 位域及位域变量的定义
位域的定义与结构定义相仿,其形式为:
struct 位域结构名
{
类型说明符 位域名1:位域长度1;
……
类型说明符 位域名n:位域长度n;
};
同样的,位域变量的定义与结构体变量定义的方式相同。可采用先定义位域后定义位域变量,同时定义或者直接定义位域变量三种方式。具体的形式此处就不再叙述。
例如,下面采用同时定义的方式定义一个位域变量field:
struct byte_struct
{
int x:8;
int y:2;
int z:6;
} field;
其表明field为byte_struct类型变量,共占2个字节。其中位域x占8位,位域y占2位,位域z占6位。如图9.13所示:
图9.13 位域变量的内存表示
3. 位域定义时注意事项
l 单个位域必须存储在同一个字节中,不能跨字节存储。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使用空域使某位域从下一单元开始。例如:
struct byte_struct
{
unsigned a:6;
unsigned :0; //空域
unsigned b:4; //从下一单元开始存放
unsigned c:4;
} two_byte;
其中,a占第一字节的6位,后2位填0表示不使用,称为空域;b从第二字节开始,占用4位,c占用4位。如图9.14所示:
图9.14 位域变量的内存表示
l 位域的长度不能大于一个字节的长度,即不能超过8位。
例如,下面的定义是非法的:
struct bs
{
unsigned a:2;
unsigned b:10; //位域长度不能大于8位
};
l 位域可以无位域名,这时其只用来做填充或调整位置,而不能使用。例如:
struct bs
{
unsigned a:4;
unsigned:4; //此4位不能使用
};
4. 位域的使用
位域从本质上说就是一种结构类型,不过其成员是按二进位分配的。所以位域的使用和结构成员的使用相同。
下面的程序清单演示了普通位域变量和指针位域变量的使用。
#include <stdio.h>
//位域声明
struct byte_struct
{
unsigned a:4;
unsigned b:2;
unsigned c:1;
};
void main()
{
struct byte_struct bit; //定义普通位域变量
struct byte_struct *pbit; //定义指针位域变量
//普通位域变量的使用
bit.a=1;
bit.b=7;
bit.c=15;
printf("%d,%d,%d/n",bit.a,bit.b,bit.c);
//指针位域变量的使用
pbit=&bit;
pbit->a=0;
pbit->b&=3;
pbit->c|=1;
printf("%d,%d,%d/n",pbit->a,pbit->b,pbit->c);
}
可以看出,位域变量的使用和结构体变量从形式上完全相同,只不过成员都是用二进制位来表示,所以会经常使用一些位操作。
最新作品《C语言参悟之旅》全新上市,敬请关注!
官方网站:http://www.tqbooks.net/product/gb/product_detail.asp?catalogid=10&productid=1474
China-pub有售:http://www.china-pub.com/49980