位域
来自 cppreference.com
声明一个具有显式宽度(以位为单位)的成员。相邻的位域成员可以打包在一起以共享和跨越单个字节。
位域声明是 结构体 或 联合体 成员声明,它使用以下 声明符
标识符 (可选) : 宽度 |
|||||||||
标识符 | - | 正在声明的位域的名称。名称是可选的:无名位域会引入指定数量的填充位。 |
宽度 | - | 一个整数 常量表达式,其值为大于或等于零且小于或等于底层类型的位数。当大于零时,这是该位域将占用的位数。值零仅允许用于无名位域,并且具有特殊含义:它指定类定义中的下一个位域将从分配单元的边界开始。 |
内容 |
[编辑] 解释
位域只能具有以下 三种(直到 C99) – 四种(自 C99 起)(直到 C23) 类型(可能具有 const 或 volatile 限定符)
- unsigned int,用于无符号位域 (unsigned int b:3; 的范围为 0..7)
- signed int,用于有符号位域 (signed int b:3; 的范围为 -4..3)
- int,用于具有实现定义的符号性的位域(注意,这与关键字
int
在其他地方的含义不同,在其他地方它表示“有符号 int”。例如,int b:3; 的取值范围可能是 0..7 或 -4..3。
|
(自 C99 起) |
|
(自 C23 起) |
可能接受其他实现定义的类型。 位域是否可以具有 原子 类型也是由实现定义的。(自 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(自 C99 起) 和(可能为 unsigned)_BitInt(N)(自 C23 起) 之外的类型是否允许
|
(自 C11 起) |
- 位域是否可以跨越分配单元边界
- 分配单元内位域的顺序(在某些平台上,位域是按从左到右排列的,而在其他平台上则是按从右到左排列的)
尽管 |
(自 C99 起) |
在 C++ 编程语言中,位域的宽度可以超过底层类型的宽度(但额外的位是填充位),并且类型为 int 的位域始终是有符号的。
[编辑] 参考资料
- C23 标准(ISO/IEC 9899:2024)
- 6.7.2.1 结构体和联合体说明符
- C17 标准(ISO/IEC 9899:2018)
- 6.7.2.1 结构体和联合体说明符
- C11 标准(ISO/IEC 9899:2011)
- 6.7.2.1 结构体和联合体说明符
- C99 标准(ISO/IEC 9899:1999)
- 6.7.2.1 结构体和联合体说明符
- C89/C90 标准(ISO/IEC 9899:1990)
- 3.5.2.1 结构体和联合体说明符
[编辑] 另请参阅
C++ 文档 中的 位域
|