5.3 位域

本篇学习位域的定义方式、适用场景和限制,并能用位域表达紧凑的标志位数据。

位域

概念说明

位域允许把结构体成员按“多少位”来分配,而不是按完整字节或完整整型分配。 它常用于状态标记、硬件寄存器映射和协议字段这类需要节省空间的场景。

位域确实方便,但它和平台实现、编译器布局关系较强。 所以它更适合明确受控的底层场景,不适合拿来做强可移植的数据交换格式。

从使用体验上看,位域像是“语法层面的位掩码包装”。 它能让字段访问更直观,但在可移植性和地址操作上没有普通成员那么自由。

语法/规则

  1. 位域通常写在结构体里,形式是 unsigned int flag : 1;
  2. 冒号后的数字表示该成员占用的位数。
  3. 位域宽度不能随意超出底层类型可提供的位数。
  4. 位域的内存布局、对齐和排列顺序与实现有关。
  5. 位域成员通常不能像普通成员那样直接取地址。
  6. 当你非常在意跨平台一致性时,手动使用位掩码往往比位域更可控。

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <stdio.h>

struct Status {
    unsigned int is_open : 1;
    unsigned int is_error : 1;
    unsigned int level : 2;
};

int main(void) {
    struct Status status = {1, 0, 3};

    printf("is_open = %u\n", status.is_open);
    printf("is_error = %u\n", status.is_error);
    printf("level = %u\n", status.level);
    return 0;
}

输出结果:

1
2
3
is_open = 1
is_error = 0
level = 3

常见错误

  1. 以为位域布局在所有平台和编译器上都完全一致。
  2. 试图对位域成员取地址,忽略了它们并不总是普通独立对象。
  3. 给位域赋超出可表示范围的值,却没有意识到高位会被截断。
  4. 把位域直接拿来描述网络协议或文件格式,却没有验证实际字节布局。
  5. 位域和位运算概念混在一起,导致调试时很难判断问题到底在布局还是在掩码逻辑。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字