位掩码(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 中的类型。
置位、清零、翻转、检测均可只影响指定位,其余位保持不变。
对第 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 已关。