11 位运算与标志位操作

四种常用操作

假设 flags 是无符号整数,mask 标出要操作的位(掩码中为 1 的位)。

操作代码含义
置位`flags= mask;`
清位flags &= ~mask;指定位清为 0,其他位不变
翻转flags ^= mask;指定位 0 ↔ 1,其他位不变
判断flags & mask结果非零表示至少有一个掩码位为 1

位从右往左编号,最低位是 bit0。1u << n 表示生成只有 bit n 为 1 的掩码(n 须在 unsigned int 的有效位宽内)。

代码示例

#include <stdint.h>

uint8_t flags = 0;
flags |=  (1u << 0);  // 00000001:置 bit0
flags |=  (1u << 1);  // 00000011:置 bit1
flags &= ~(1u << 0);  // 00000010:清 bit0
flags ^=  (1u << 2);  // 00000110:翻转 bit2

if (flags & (1u << 1)) {
    // bit1 已置位
}

记忆: |= 置 1,&= ~ 清 0,^= 翻转,& 检查。

蓝牙/TWS 开发注意

  • 多状态可以共用一个 flags,每一位代表一个独立状态;设置某一位时尽量避免 flags = mask 覆盖其他状态。
  • if (flags & mask) 判断的是至少一位被设置;要判断掩码中全部位都已设置,用 (flags & mask) == mask。
  • 软件状态变量与硬件寄存器不同:某些寄存器有写 1 清零(W1C)、只读或读写副作用,不能不加分析地使用 |=、&= ~ 等读—改—写操作。
  • 多线程或中断同时修改同一标志变量时,普通的 |= 等并不自动保证原子性;需根据平台采用临界区、原子操作或其他同步机制。