Wetts's blog

Stay Hungry, Stay Foolish.

0%

C-类型-结构体-位域

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有 0 和 1 两种状态,用 1 位二进位即可。为了节省存储空间,并使处理简便,C 语言又提供了一种数据结构,称为”位域”或”位段”。

所谓”位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

典型的实例:

  • 用 1 位二进位存放一个开关量时,只有 0 和 1 两种状态。
  • 读取外部文件格式——可以读取非标准的文件格式。例如:9 位的整数。

位域的定义和位域变量的说明

位域定义与结构定义相仿,其形式为:

1
2
3
4
struct 位域结构名
{
位域列表
};

其中位域列表的形式为:

1
类型说明符 位域名 : 位域长度

例如:

1
2
3
4
5
struct bs{
int a:8;
int b:2;
int c:6;
}data;

说明 data 为 bs 变量,共占两个字节。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。

对于位域的定义尚有以下几点说明:

  • 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。

    1
    2
    3
    4
    5
    6
    struct bs{
    unsigned int a:4;
    unsigned int :4; /* 空域 */
    unsigned int b:4; /* 从下一单元开始存放 */
    unsigned int c:4
    }
  • 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。如果最大长度大于计算机的整数字长,一些编译器可能会允许域的内存重叠,另外一些编译器可能会把大于一个域的部分存储在下一个字中。

  • 位域可以是无名位域,这时它只用来作填充或调整位置。无名的位域是不能使用的。

    1
    2
    3
    4
    5
    6
    struct k{
    int a:1;
    int :2; /* 该 2 位不能使用 */
    int b:3;
    int c:2;
    };

使用

位域的使用和结构成员的使用相同,其一般形式为:

1
2
位域变量名.位域名
位域变量名->位域名