首页 > 编程笔记 > C语言笔记 阅读:13

C语言位域的用法(附带实例)

位域(又叫位段)是一种特殊的结构体类型,其所有成员的长度均以二进制位为单位进行定义,结构体中的成员被称为位域。

C语言中,位域的一般定义形式如下:
struct 结构体名
{
    类型 变量名1:长度;
    类型 变量名2:长度;
    …
    类型 变量名n:长度;
}

一个位域必须是 int、unsigned 或 signed 中的一种。例如,CPU 的状态寄存器按位域类型定义如下:
struct status
{
    unsigned sign:1;        /*符号标志*/
    unsigned zero:1;        /*零标志*/
    unsigned carry:1;       /*进位标志*/
    unsigned parity:1;      /*奇偶溢出标志*/
    unsigned half_carry:1;  /*半进位标志*/
    unsigned negative:1;     /*减标志*/
} flags;

显然,对 CPU 的状态寄存器而言,使用位域类型仅需 1 个字节即可。又如:
struct packed_data
{
    unsigned a:2;
    unsigned b:1;
    unsigned c:1;
    unsigned d:2;
}data;
可以发现,这里 a、b、c、d 分别占 2 位、1 位、1 位、2 位,如下图所示。


图 1 占位情况

C语言位域的说明

前面介绍了什么是位域,这里针对位域的应用,有以下几点说明:

1) 位域类型和位域变量的定义,以及位域成员的引用,均与结构体类型和结构体变量相同。

2) 在下面定义的位域结构中,各位域都只占用一个二进制位:
struct attribute
{
    unsigned font:1;
    unsigned color:1;
    unsigned size:1;
    unsigned dir:1;
};

如果某位域需要表示多于两种状态,也可将该位域设置为占用多个二进制位。例如,字体大小有 4 种状态,则可将上面的位域结构改写成如下形式:
struct attribute
{
    unsigned font:1;
    unsigned color:1;
    unsigned size:2;
    unsigned dir:1;
};

3) 某一位域要从另一个字节开始存放,可写成如下形式:
struct status
{
    unsigned a:1;
    unsigned b:1;
    unsigned c:1;
    unsigned :0;
    unsigned d:1;
    unsigned e:1;
    unsigned f:1;
}flags;
原本 a、b、c、d、e、f 这 6 个位域是连续存储在一个字节中的。由于加入了一个长度为 0 的无名位域,因此其后的 3 个位域从下一个字节开始存储,一共占用两个字节。

4) 可以使各位域占满一个字节,也可以不占满一个字节。例如:
struct packed_data
{
    unsigned a:2;
    unsigned b:2;
    unsigned c:1;
    int i;
}data;
存储形式如下图所示:


图 2 不占满一个字节的情况

5) 一个位域必须存储在一个存储单元(通常为 1 字节)中,不能跨两个存储单元。如果本单元不够容纳某位域,则从下一个单元开始存储该位域。

6) 可以用“%d”、“%x”、“%u”、“%o”等格式字符,以整数形式输出位域。

7) 在数值表达式中引用位域时,系统自动将位域转换为整型数。

相关文章