4 位运算基础
正在加载视频播放器…
GESP C++ 三级:位运算精讲
核心目标:掌握六种位运算符
& | ^ ~ << >>的规则与运算方法,理解补码下的位运算,能熟练求值、判断奇偶、交换变量、取位/设位/清位、统计 1 的个数。
位运算直接操作二进制补码;&同 1 为 1,|有 1 为 1,^不同为 1,~取反,<<左移乘 2 的幂,>>右移除 2 的幂。
一、位运算基础
1. 什么是位运算
位运算是直接对整数的二进制补码逐位进行操作的运算。计算机中所有整数都以补码存储,因此位运算对正数和负数都适用。
2. 补码回顾
- 正数:原码 = 反码 = 补码。
- 负数:补码 = 反码 + 1。
- 8 位补码范围:-128 ~ 127。
- 位运算时,先写出操作数的补码,逐位运算,结果再按补码解释。
3. 六种位运算符总览
| 运算符 | 名称 | 运算规则 | 优先级 |
|---|---|---|---|
~ |
按位非 | 每一位取反,0 变 1,1 变 0 | 高 |
<< |
左移 | 所有位左移,右边补 0 | 中 |
>> |
右移 | 所有位右移,左边补符号位 | |
& |
按位与 | 两个位都为 1 时结果为 1 | 低 |
^ |
按位异或 | 两个位不同时结果为 1 | |
| ` | 按位或 | 两个位有一个为 1 时结果为 1 | |
注意:位运算符优先级低于算术运算符,不确定时加括号。
&和|不要与逻辑运算符&&、||混淆。
二、按位与 &
1. 规则
两个相应位都为 1 时,结果位才为 1,否则为 0。
1010 1100
& 1100 1010
──────────
1000 1000
2. 示例
int a = 5; // 0101
int b = 3; // 0011
cout << (a & b) << endl; // 0001 = 1
3. 常见用途
| 用途 | 写法 | 说明 |
|---|---|---|
| 判断奇偶 | n & 1 |
结果为 1 是奇数,0 是偶数 |
| 取某一位 | (n >> k) & 1 |
取第 k 位(从 0 开始) |
| 清零某一位 | n & ~(1 << k) |
第 k 位变 0 |
| 保留某些位 | n & mask |
mask(掩码) 中为 1 的位保留 |
(mask掩码:用一串二进制数字当 “遮罩”,只保留想要的二进制位,屏蔽其他位。)
三、按位或 |
1. 规则
两个相应位中有一个为 1,结果位就为 1。
1010 1100
| 1100 1010
──────────
1110 1110
2. 示例
int a = 5; // 0101
int b = 3; // 0011
cout << (a | b) << endl; // 0111 = 7
3. 常见用途
| 用途 | 写法 | 说明 |
|---|---|---|
| 设置某一位为 1 | `n | (1 << k)` |
四、按位异或 ^
1. 规则
两个相应位不同时结果为 1,相同时为 0。
1010 1100
^ 1100 1010
──────────
0110 0110
2. 示例
int a = 5; // 0101
int b = 3; // 0011
cout << (a ^ b) << endl; // 0110 = 6
3. 常见用途
| 用途 | 写法 | 说明 |
|---|---|---|
| 交换两个变量 | a ^= b; b ^= a; a ^= b; |
无需临时变量 |
| 判断相等 | a ^ b == 0 |
相等则结果为 0 |
| 翻转某一位 | n ^ (1 << k) |
第 k 位取反 |
| 找只出现一次的数 | 全部异或 | 其他数出现两次 |
五、按位非 ~
1. 规则
每一位取反,0 变 1,1 变 0。
~ 0000 0101
──────────
1111 1010
2. 示例
int a = 5; // 0000 0101
cout << ~a << endl; // 1111 1010,补码解释为 -6
3. 重要结论
对于整数 n,~n = -n - 1。
~5 == -6
~0 == -1
~-1 == 0
4. 常见用途
- 配合
&清零某一位:n & ~(1 << k)。 - 构造掩码。
六、左移 <<
1. 规则
所有位向左移动指定的位数,右边空出的位补 0。
0000 0101 << 1
──────────────
0000 1010
2. 示例
int a = 5;
cout << (a << 1) << endl; // 10
cout << (a << 2) << endl; // 20
cout << (a << 3) << endl; // 40
3. 数学意义
左移 n 位相当于乘以 。
a << 1 == a * 2
a << 2 == a * 4
a << 3 == a * 8
4. 常见用途
- 快速乘以 2 的幂。
- 构造
1 << k表示第 k 位为 1 的掩码。 - 位运算题目中用于取位、设位。
5. 注意
左移可能导致溢出,超出类型范围时结果不确定。
七、右移 >>
1. 规则
所有位向右移动指定的位数。
0000 1010 >> 1
──────────────
0000 0101
2. 示例
int a = 20;
cout << (a >> 1) << endl; // 10
cout << (a >> 2) << endl; // 5
3. 数学意义
右移 n 位相当于除以 ,向下取整。
a >> 1 == a / 2
a >> 2 == a / 4
a >> 3 == a / 8
4. 负数右移
负数右移是算术右移,左边补符号位(1),结果向下取整。
-5 >> 1 // -3,不是 -2
因为 -5 的补码右移一位后,结果补码解释为 -3。
5. 注意
- 右移不改变符号位。
- 对负数右移要小心,不要简单理解为除以 2。
八、位运算优先级
从高到低:
~
<< >>
&
^
|
但整体上,位运算符优先级低于算术运算符。例如:
1 << 2 + 3 // 先算 2+3=5,再算 1<<5 = 32
(1 << 2) + 3 // 先算 1<<2=4,再加 3 = 7
建议:不确定时加括号。
九、位运算与逻辑运算的区别
| 位运算 | 逻辑运算 | 区别 |
|---|---|---|
& |
&& |
& 逐位与,&& 整体逻辑与 |
| ` | ||
~ |
! |
~ 逐位取反,! 逻辑非 |
^ |
无 | 异或,不同为 1 |
示例:
5 & 3 // 1
5 && 3 // true(非零即真)
5 | 3 // 7
5 || 3 // true
十、常见应用汇总
| 需求 | 写法 | 说明 |
|---|---|---|
| 判断奇偶 | n & 1 |
1 奇,0 偶 |
| 乘以 2 的 n 次方 | n << n |
如 n << 3 等于 n * 8 |
| 除以 2 的 n 次方 | n >> n |
如 n >> 2 等于 n / 4 |
| 交换两个变量 | a ^= b; b ^= a; a ^= b; |
无需临时变量 |
| 取第 k 位 | (n >> k) & 1 |
从 0 开始计数 |
| 设置第 k 位为 1 | `n | (1 << k)` |
| 清零第 k 位 | n & ~(1 << k) |
|
| 翻转第 k 位 | n ^ (1 << k) |
|
| 统计二进制中 1 的个数 | 循环 n & 1 后 n >>= 1 |
或用 __builtin_popcount |
| 判断是否为 2 的幂 | n > 0 && (n & (n - 1)) == 0 |
2 的幂只有一位为 1 |
十一、GESP 三级真题示例
1. 2025年6月 第8题
二进制数
1010 | 1100的结果是( )
A) 1000 B) 1110 C) 0110 D) 1100
答案:B
解析:逐位或,1010 | 1100 = 1110。
2. 2025年6月 第9题
以下哪个位运算可以交换两个变量的值,且不需要临时变量?( )
A)&B)|C)^D)~
答案:C
解析:a ^= b; b ^= a; a ^= b;可交换。
3. 2026年3月 第8题
0000 1111 << 3的结果是( )
A) 0111 1000 B) 0001 1110 C) 1000 0111 D) 1111 0000
答案:A
解析:0000 1111左移 3 位,右边补 0,得0111 1000。
4. 三级样题
一个
int类型的值乘以 8,等价于( )
A)<< 2B)<< 3C)>> 2D)>> 3
答案:B
解析:乘以 8 等于乘以 ,即左移 3 位。
十二、易错点
- 位运算基于补码,负数参与运算时先转补码。
~n = -n - 1,不要忘记负数结果。<<左移可能溢出,超出类型范围结果不确定。>>对负数是算术右移,向下取整,不是简单丢弃。^是异或,不是幂运算。- 不要混淆
&和&&、|和||。 - 位运算符优先级低于算术运算符,建议加括号。
- 左移位数不能为负数,也不能超过类型位数。
- 交换变量时三个异或语句顺序不能错。
- 统计 1 的个数时,注意负数补码中 1 的个数较多。
十三、速查表
| 运算 | 规则 | 示例 |
|---|---|---|
a & b |
同 1 为 1 | 5 & 3 = 1 |
| `a | b` | 有 1 为 1 |
a ^ b |
不同为 1 | 5 ^ 3 = 6 |
~a |
取反 | ~5 = -6 |
a << n |
左移 n 位,乘 | 5 << 1 = 10 |
a >> n |
右移 n 位,除 | 20 >> 2 = 5 |
n & 1 |
判断奇偶 | 1 奇,0 偶 |
a ^= b; b ^= a; a ^= b; |
交换变量 | 无需临时变量 |
(n >> k) & 1 |
取第 k 位 | 从 0 开始 |
| `n | (1 << k)` | 设置第 k 位为 1 |
n & ~(1 << k) |
清零第 k 位 | |
n ^ (1 << k) |
翻转第 k 位 |
十四、总结
位运算是 GESP 三级的核心考点。
- 位运算直接操作二进制补码。
&同 1 为 1,|有 1 为 1,^不同为 1,~取反。<< n相当于乘以 ,>> n相当于除以 。- 负数右移是算术右移,向下取整。
~n = -n - 1。n & 1判断奇偶。- 异或可以交换两个变量。
(n >> k) & 1取第 k 位。n | (1 << k)设置位,n & ~(1 << k)清零位。- 位运算优先级低于算术运算,不确定时加括号。
复习建议:重点练习位运算表达式求值、程序阅读写结果、交换变量、判断奇偶、取位/设位/清位、统计 1 的个数。考试中先写出补码,再逐位运算,最后按补码解释结果。多练真题中的选择题和程序阅读题,注意负数右移和优先级陷阱。