一、先说结论:不是多此一举,是 C 语言寄存器操作的经典编码习惯
tmpReg &= ~0xFFFF0000等价于tmpReg = tmpReg & 0x0000FFFF
明明可以直接写& 0x0000FFFF,很多工程师偏爱用& ~掩码写法,主要三个原因:
1. 语义直观:你要清零哪几位,就写哪几位的掩码
需求:我要清零高 16 位
- 高 16 位:
0xFFFF,低 16 位:0x0000→ 掩码写0xFFFF0000 - 加
~取反后,要清零的位变成 0,要保留的位变成 1
读代码一眼就能看懂:~0xFFFF0000→ 把0xFFFF0000标记的这些位清零。
如果直接写0x0000FFFF: 你得在脑子里反向换算一遍:哪几位是 1、哪几位用来保留,可读性差。
举个例子
要清零 bit3、bit5:
reg &= ~((1<<3)|(1<<5));一眼看出:把 bit3、bit5 清零。 如果手动算掩码写成reg & 0xFFFFFFD7,谁能一眼看懂清了哪几位?
2. 统一编码规范:位操作三种标准写法,格式统一
- 置 1 某几位:
reg |= 掩码 - 清零某几位:
reg &= ~掩码 - 翻转某几位:
reg ^= 掩码
规则统一: 掩码永远写需要操作的位为 1。
- 置 1:哪些位要设 1,掩码哪些位写 1
- 清零:哪些位要清 0,掩码哪些位写 1,然后取反
如果清零不用~,就要手动写反向掩码,三种操作写法逻辑不一致,容易写错。
3. 避免手算出错,减少低级错误
比如要清除 bit8~bit15 共 8 位:
- 方式 1(取反写法):掩码直接写
0x00FF00,reg &= ~0x00FF00 - 方式 2(直接掩码):需要自己算出
0xFF00FF,很容易算错十六进制
位越多、分散位越多,手动算反向掩码越容易出错,用~可以直接按照操作目标写掩码,不用反向计算。
二、两种写法效果完全一样
tmpReg &= ~0xFFFF0000;tmpReg &= 0x0000FFFF;
机器执行结果一模一样,没有性能差异,只是人为可读性、编码规范层面的写法选择。
三、补充:什么时候直接写正向掩码?
只有连续低位保留、简单场景才会直接写0x0000FFFF; 但凡零散位、中间几段位清零,一律用& ~掩码。