位运算符 & | ^ ~ 把数按二进制对齐、一位对一位地算:& 是串联开关(双 1 才出 1)、| 是并联开关(有 1 就出 1)、^ 是"不同才亮"、~ 是整排全翻转。零开销哲学的亲儿子——最贴近硬件的一组运算。
一、先把二进制搬回来
回看 2.2.1:同一个数有四种进制写法,二进制前缀 0b。位运算的工作台就是二进制:
5 = 0b101
3 = 0b011
位运算的操作流程:把两个数的二进制右对齐(像列竖式),然后一位对一位独立地算——每一位的结果只看这两位,跟隔壁位无关。这和十进制加法"满十进位"完全不同——位运算没有进位。
二、四个符号逐个演
以 5 = 101、3 = 011(右对齐)为例:
& 位与——双 1 才出 1(串联开关)
101 (5)
& 011 (3)
-----
001 → 5 & 3 = 1
每一竖列:1&1=1,0&1=0,1&1=1 → 结果 001。只有两位都是 1,那一位才是 1——像串联电路,两个开关都闭合灯才亮。
| 位或——有 1 就出 1(并联开关)
101 (5)
| 011 (3)
-----
111 → 5 | 3 = 7
任何一位有 1,结果那位就是 1。注意:位运算的 | 跟逻辑的 || 长得像但完全两码事(区别见误区 3)。
^ 异或——不同才出 1
101 (5)
^ 011 (3)
-----
110 → 5 ^ 3 = 6
两位相同(1,1 或 0,0)出 0,不同出 1。两个好记的性质:a ^ a = 0(自己跟自己全同)、a ^ 0 = a(0 不改变任何位)。用途:把某些位翻转、简易加密(同一把"钥匙"再异或一次就还原)。
~ 位反——整排全翻转(一元)
~5 把 5 的所有二进制位 0↔1。注意 int 是 32 位,前面还有一大串 0 也一起翻成 1,而最高位翻成 1 后按补码解读就是负数——~5 的结果是 -6。现阶段不用深究补码细节,记住"~ 是全翻转、对 int 结果是负的"即可。
三、位运算的真实用途:掩码(mask)
& 最重要的用途是掩码——用一个精心挑的数,去"筛"另一个数的某些位:
// 判断奇偶:n & 1
// 任何数 & 1,只保留最低位:最低位是 1 就是奇数
cout << (7 & 1) << endl; // 1 → 奇
cout << (8 & 1) << endl; // 0 → 偶
// 取低 4 位:n & 0xF
int n = 0b10110110;
cout << (n & 0xF) << endl; // 0b0110 = 6,高 4 位被筛掉
为什么 & 能筛位?掩码里为 0 的位置,& 完必为 0(被关掉);掩码里为 1 的位置,原样放行。这就是嵌入式、图形处理、权限标记天天用的操作。教材实例 02 演示的就是这一套。
四、动手 Demo:教材实例02 的思路复现
#include <iostream>
using namespace std;
int main() {
int a = 5, b = 3;
cout << "a & b = " << (a & b) << endl; // 1
cout << "a | b = " << (a | b) << endl; // 7
cout << "a ^ b = " << (a ^ b) << endl; // 6
cout << "~a = " << (~a) << endl; // -6
// 掩码三连
int n = 13; // 0b1101
cout << "奇偶 " << (n & 1) << endl; // 1(奇)
cout << "低2位 " << (n & 3) << endl; // 1(0b01)
int flag = n | 0b10; // 把第 2 位置 1:1101 | 0010 = 1111
cout << "置位后 " << flag << endl; // 15
return 0;
}
看到什么算成功:1 7 6 -6 1 1 15。每行都建议先在纸上手算,再跟输出对——位运算全靠手感,手感靠手算。
30 秒实验:n ^ n 输出 0,n ^ 0 输出 n 本身——亲手验证"异或自反"性质;再把 n | 0b10 换成 n & ~0b10,看第 2 位被清 0(置位用 |、清位用 & ~,一对好搭档)。
五、常见误区
- "位运算结果看起来乱七八糟"——不是乱,是你在用十进制看二进制的操作。先写二进制竖式,一切都有迹可循。
- "
5 & 3等于5 && 3"——不等!5 && 3是逻辑且:两个都非 0,结果是1;5 & 3是位与:按位算,结果是1——这回碰巧相等,但5 & 2 = 0而5 && 2 = 1。逻辑判断用双写,位操作用单写。 - "
~5应该等于 2"(只翻 101 的三位)——~ 翻转的是全部 32 位,包括前导的 29 个 0。 - "
n & 1判奇偶是炫技"——是惯例。n % 2对负数的余数符号要操心,n & 1永远只看最低位,结果非 0 即奇。两个都认识,位运算版更快更稳。
自测四问(点开对答案)
1. `12 & 10` 等于多少?——`8`(1100 & 1010 = 1000)。 2. `12 | 10` 呢?——`14`(1110)。 3. `5 ^ 5` 和 `5 ^ 0`?——`0` 和 `5`(自反性质)。 4. 掩码 `n & 1` 结果为 0 说明什么?——最低位是 0,n 是偶数。- ☐ 3.1.6 移位运算符(下一节,含实例03)