C参考手册
C 语法
Bit fields
以位为单位声明一个明确宽度的成员。相邻的位字段成员可以打包以共享和跨越单个字节。
位字段声明是使用以下声明的结构或联合成员声明:
identifier(optional) : width |
|
|
---|
标识符 |
- |
正在声明的位字段的名称。该名称是可选的:无名称位域引入了指定的填充位数 |
---|---|---|
宽度 |
- |
一个整数常量表达式,其值大于或等于零且小于或等于基础类型中的位数。当大于零时,这是该位字段将占用的位数。值零只能用于无名的位域,具有特殊含义:它指定类定义中的下一个位域将从分配单元的边界开始。 |
说明
位域只能有四种类型之一(可能是 const 或 volatile 限定的):
-
unsigned int
,对于无符号位域(unsigned int b:3;
有范围0..7
) -
signed int
,对于有符号位域(signed int b:3;
有范围-4..3
) -
int
,对于具有实现定义的签名的位字段(请注意,这与int
其他地方的关键字的含义不同,它表示“signed int”)。例如,int b:3;
可能有值的范围0..7
或-4..3
。 -
_Bool
,用于单位位域(bool x:1;
具有范围0..1
和隐式转换,它遵循布尔转换规则。
额外的实现定义类型可能是可以接受的。它也是实现定义是否一个位域可能有原子类型。(自 C11开始)位域(宽度)中的位数将限制设置为可容纳的值范围:
#include <stdio.h>
struct S {
// three-bit unsigned field,
// allowed values are 0...7
unsigned int b : 3;
};
int main(void)
{
struct S s = {7};
++s.b; // unsigned overflow
printf("%d\n", s.b); // output: 0
}
允许多个相邻位字段(通常是)打包在一起:
#include <stdio.h>
struct S {
// will usually occupy 4 bytes:
// 5 bits: value of b1
// 11 bits: unused
// 6 bits: value of b2
// 2 bits: value of b3
// 8 bits: unused
unsigned b1 : 5, : 11, b2 : 6, b3 : 2;
};
int main(void)
{
printf("%zu\n",sizeof(struct S)); // usually prints 4
}
宽度为零的特殊未命名位字段分隔填充:它指定下一个位字段从下一个分配单元的开始处开始:
#include <stdio.h>
struct S {
// will usually occupy 8 bytes:
// 5 bits: value of b1
// 27 bits: unused
// 6 bits: value of b2
// 15 bits: value of b3
// 11 bits: unused
unsigned b1 : 5;
unsigned :0; // start a new unsigned int
unsigned b2 : 6;
unsigned b3 : 15;
};
int main(void)
{
printf("%zu\n", sizeof(struct S)); // usually prints 8
}
由于位字段不一定在字节的开始处开始,所以不能采用位字段的地址。指向位字段是不可能的。位字段不能与 sizeof 和 alignas 一起使用(自 C11开始)。
注意
位字段的以下属性未定义:
- 调用
offsetof
位域的效果
位字段的以下属性未指定:
- 保存位域的分配单元的对齐
位域的以下属性是实现定义的:
- 类型的位字段是否
int
被视为有符号或无符号 - 是否允许 int,signed int,unsigned int和_Bool 以外的类型
- 原子类型是否被允许
- 位域是否可以跨越分配单位边界
- 分配单元中的位字段的顺序(在某些平台上,位字段从左到右打包,其他从右到左)
即使对象表示中的位数_Bool
至少CHAR_BIT
为_Bool
1 ,类型的位字段的宽度也不能大于1。
在 C ++编程语言中,位域的宽度可以超过基础类型的宽度。
参考
- C11 standard (ISO/IEC 9899:2011):
- 6.7.2.1 Structure and union specifiers
- C99 standard (ISO/IEC 9899:1999):
- 6.7.2.1 Structure and union specifiers
- C89/C90 standard (ISO/IEC 9899:1990):
- 3.5.2.1 Structure and union specifiers