文章

C++ 位域

C++ 位域

C++位域(Bit Field)是一种允许在结构体(struct)或联合体(union)中以位为单位分配存储空间的特性,用来节省内存或实现与硬件寄存器的精准映射

基本语法

1
2
3
4
5
strcut Example {
	unsigned int a : 3;	// a占3位
	unsigned int b : 5; // b占5位
	unsigned int c : 8; // c占8位
}

在这里,a占3位,b占5位,c占8位

所有成员依然是unsigned int类型,只是存储时按照指定的位数压缩

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;

struct Flags {
    unsigned int isVisible : 1;
    unsigned int isEnabled : 1;
    unsigned int hasFocus  : 1;
    unsigned int reserved  : 5;  // 用于对齐或保留
};

int main() {
    Flags f = {1, 0, 1, 0};
    cout << "Visible: " << f.isVisible << endl;
    cout << "Enabled: " << f.isEnabled << endl;
    cout << "HasFocus: " << f.hasFocus << endl;

    cout << "sizeof f: " << sizeof(f) << endl;
    cout << "sizeof Flags: " << sizeof(Flags) << endl;
    return 0;
}

输出:

1
2
3
4
5
Visible: 1
Enabled: 0
HasFocus: 1
sizeof f: 4
sizeof Flags: 4

在这个程序中,结构体总共占了8位数,即1个字节,但是unsigned int的大小为4,所以sizeof(Flags)的输出结果通常是4

未命名位域与零宽度位域

  • 未命名位域(Unnamed Bit-fields)

    1
    2
    
      // type : width;
      int : 8;
    

    这会产生一个指定宽度的匿名位域,主要用于填充,即跳过指定的位数

    这些位无法被直接访问

  • 零宽度未命名位域(Zero-width Unnamed Bit-field)

    1
    2
    
      // type : 0;
      int : 0;
    

    这是一个特殊命令,它会强制下一个位域成员从下一个基础类型的边界开始对齐

1
2
3
4
5
6
7
struct LayoutControl {
    unsigned char a : 3;
    unsigned char   : 2; // 跳过 2 位
    unsigned char b : 3;
    unsigned int    : 0; // 强制下一个成员在新的 unsigned int 边界开始
    unsigned int c : 5;
};

特点

特性说明 
类型位域必须是整型或枚举类型(如 int, unsigned int, signed int)。 
宽度宽度由冒号后的常量表达式指定(例如 : 3)。 
取值范围对于 n 位的无符号位域,可表示 0 ~ 2^n - 1;有符号则是 -(2^(n-1)) ~ 2^(n-1)-1 
内存对齐位域通常打包在同一个 int 内存单元中,但实现依赖于编译器。 
不可取地址或引用位域成员 不能取地址,例如:&f.isVisible ❌。 
不能创建数组不能声明位域数组 
不能是static位域不能声明为静态成员 
跨单元禁止共享如果剩余位不足以容纳下一个位域,编译器会从下一个整型单元开始存放。 

常见用途

应用场景示例
节省内存嵌入式系统或通信协议中保存大量布尔标志位。
硬件寄存器映射与硬件设备寄存器的一位一位对应。
网络协议头如 TCP/IP 报文头结构的位级定义。
本文由作者按照 CC BY 4.0 进行授权