📘位运算与或非

2026-08-16
⭐⭐ GESP 5级

📖概念讲解

位运算是直接对整数的二进制位进行操作的运算符,属于 C++ 基础运算中的重要一类。GESP 5 级要求掌握四种:

运算符名称规则
&按位与 AND两位都为 1 才得 1
|按位或 OR任一为 1 就得 1
^按位异或 XOR不同为 1,相同为 0
~按位取反 NOT0→1,1→0(包括符号位)
💡 核心记忆:& 取交集,| 取并集,^ 取差集。~ 是"全部翻转",注意 ~0 = -1(补码全1)。

易错重点:位运算优先级低于比较运算符 == !=,所以 a & b == 0 实际等价于 a & (b == 0),必须加括号:(a & b) == 0。

💻代码示例

1#include <iostream>
2using namespace std;
3
4int main() {
5 int a = 12, b = 10; // a=0110, b=1010 (二进制)
6
7 // 按位与 &:两位都为1才为1 → 取公共部分
8 cout << "a & b = " << (a & b) << endl; // 8 → 1000
9
10 // 按位或 |:任一为1就为1 → 合并所有1
11 cout << "a | b = " << (a | b) << endl; // 14 → 1110
12
13 // 按位异或 ^:不同为1,相同为0
14 cout << "a ^ b = " << (a ^ b) << endl; // 6 → 0110
15
16 // 按位取反 ~:全部翻转(补码)
17 cout << "~a = " << ~a << endl; // -13 (补码全1后+1)
18
19 // ⚠️ 经典陷阱:a & b == 0 实际是 a & (b==0)!
20 cout << "(a & b) == 0 ? " << ((a & b) == 0) << endl; // 0(不等于0)
21 cout << "a & (b==0) = " << (a & (b == 0)) << endl; // 0(b!=0所以b==0为0)
22
23 // 异或经典技巧:a ^ a = 0, a ^ 0 = a
24 cout << "a ^ a = " << (a ^ a) << endl; // 0(自己异或自己=0)
25 cout << "a ^ 0 = " << (a ^ 0) << endl; // 12(异或0不变)
26
27 return 0;
28}

# 输出:a & b = 8, a | b = 14, a ^ b = 6, ~a = -13, (a & b)==0 ? 0, a & (b==0) = 0, a ^ a = 0, a ^ 0 = 12

🧩互动小测

Q1:表达式 (5 ^ 3) & 6 的结果是?

Q2:下面哪个表达式可以「不使用临时变量交换两个 int」?

Q3:~0 的结果(32位 int)是?

🏋️动手练一练

📝 编程练习

给定两个正整数 a 和 b,输出它们的二进制表示中不同的位数(即 a ^ b 的结果中 1 的个数)。

输入:两个正整数 a, b(均 ≤ 109)
输出:一个整数,表示 a 和 b 二进制不同的位数

提示:用异或得到不同的位,再逐位统计 1 的个数。也可以用 x & (x-1) 技巧:每次消去最低位的 1。
参考答案:
#include<iostream>
using namespace std;
int main(){
    int a,b;
    cin>>a>>b;
    int x=a^b;       // 异或:不同位变1
    int cnt=0;
    while(x){
        x=x&(x-1);   // 消去最低位的1
        cnt++;        // 每消一个就+1
    }
    cout<<cnt<<endl;
    return 0;
}

要点:x & (x-1) 是经典位运算技巧,能 O(k) 时间(k 为 1 的个数)统计二进制中 1 的个数,比逐位扫描更高效。

📝易错点提醒

学完这个知识点后点一下