位掩码(bit masking)指在整数类型上按二进制位进行读写:将每一位视为一个独立的开关(flag),用 0、1 表示关、开。多个布尔状态可打包在一个 int 或 short 中,节省存储并便于与硬件寄存器、权限位等模型对应。相关运算符见运算符中的按位运算。

布尔运算与位

运算规则
NOT(非)1→0,0→1
AND(与)两位均为 1 时结果为 1
OR(或)任一位为 1 时结果为 1
XOR(异或)两位不同时结果为 1

一个二进制位可表示一个布尔量。char、int 等类型由若干位组成;C 标准规定 char 至少 8 位、int 至少 16 位。需要固定位宽时可使用 stdint.h 中的类型。

0b 0000 0101 表示 FLAG_ALIVE(bit2) 和 FLAG_ON(bit0) 都开着 0 bit7 0 bit6 0 bit5 0 bit4 0 bit3 1 bit2 0 bit1 1 bit0 开 开 第 n 位表示一个 flag:1 为开,0 为关
置位、清零、翻转、检测均可只影响指定位,其余位保持不变。

对第 n 位的四种操作

掩码常写为 1 << n,将 1 移到第 n 位:

/* 置位:第 n 位设为 1 */
storage |= (1 << n);

/* 清零:第 n 位设为 0 */
storage &= ~(1 << n);

/* 翻转:第 n 位 0 与 1 互换 */
storage ^= (1 << n);

/* 检测:第 n 位是否为 1 */
bit = storage & (1 << n);   /* 非 0 表示该位为 1 */

置位

01000010   (storage)
   OR
00001000   (1 << 3)
   ==
01001010

按位 OR 仅将目标位变为 1,其余位保持原值。

清零

01001010
   AND
11110111   (~(1 << 3))
   ==
01000010

翻转

01000010    01001010
   XOR         XOR
00001000    00001000
   ==          ==
01001010    01000010

检测

01000010    01001010
   AND         AND
00001000    00001000
   ==          ==
00000000    00001000

后者结果非零,表示第 3 位为 1。

示例:组合多个标志位

const short FLAG_ON           = 1 << 0;
const short FLAG_MOVEMENT     = 1 << 1;
const short FLAG_TRANSPARENT  = 1 << 2;
const short FLAG_ALIVE        = 1 << 3;
const short FLAG_BROKEN       = 1 << 4;
const short FLAG_EDIBLE       = 1 << 5;

int main(void) {
    short attributes = 0;

    attributes |= FLAG_ON;
    attributes |= FLAG_TRANSPARENT;
    attributes |= FLAG_BROKEN;

    attributes &= FLAG_ON | FLAG_ALIVE;

    if (attributes & FLAG_ALIVE) {
        /* FLAG_ALIVE 已置位 */
    }
    if (!(attributes & FLAG_BROKEN)) {
        /* FLAG_BROKEN 未置位 */
    }
    return 0;
}

一个 short 可编码多达 16 个独立标志,相比为每个状态单独使用整型变量更省空间。

适用场合

  • 权限或能力集合(读、写、执行等位的组合)。
  • 驱动或协议中的状态寄存器按位解释。
  • 需要在一处集中保存大量二值状态的场景。

练习:在理解置位、清零与检测的基础上,将 attributes 调整为仅 FLAG_ON 与 FLAG_ALIVE 为 1,并用位运算验证 FLAG_ALIVE 已开、FLAG_BROKEN 已关。