原始题目
以下代码的输出是什么?
#include <iostream>
using namespace std;
int main() {
int a = 3;
cout << (a << 2 | 1) << endl;
return 0;
}
答案:13
三步算出结果
a = 3,二进制是11- 先算
a << 2:11左移 2 位 →1100= 12 - 再算
| 1:最低位置 1 →1101= 13
a = 0000 0011 (3)
a << 2 = 0000 1100 (12) ← 左移 2 位 = ×4
| 1 = 0000 1101 (13) ← 最低位置 1
真正的考点:<< 和 | 谁先算
很多人以为位运算都是“从左到右”算,其实优先级不一样:
\[ \texttt{<<} \ \texttt{>>} \ > \ \texttt{\&} \ > \ \texttt{\textasciicircum} \ > \ \texttt{|} \]
移位运算 << 的优先级高于按位或 |,所以:
a << 2 | 1 == (a << 2) | 1 = 13 ✅
如果误以为 | 先算,就会得到:
a << (2 | 1) = 3 << 3 = 24 ❌
记忆口诀:位运算家族里,移位最“紧”,
&次之,^再次,|最松。 所以混写时一定加括号,既别人看得懂,也不怕记错优先级。
常见写法对比(a = 3)
| 表达式 | 等价写法 | 结果 | 二进制 |
|---|---|---|---|
a << 2 |
(a << 2) |
12 | 1100 |
a << 2 \| 1 |
(a << 2) \| 1 |
13 | 1101 |
a << (2 \| 1) |
a << 3 |
24 | 11000 |
(a \| 1) << 2 |
— | 12 | 1100 |
a << 2 + 1 |
a << 3 |
24 | 11000 |
最后一行也很坑:算术 + 的优先级同样高于移位 <<,所以 a << 2 + 1 是 a << (2+1),不是 (a<<2)+1。
这段代码的语义
a << 2 | 1 实际在做两件事:
a << 2:把 a 乘 4| 1:把结果最低位置 1
合起来就是:a × 4 后再把最低位强制变成 1(如果末位已经是 1,值保持不变)。
// 等价写法(对非负 a)
int r = (a * 4) | 1;
实用小技巧
x | 1 // 把 x 变成不小于 x 的最小奇数(末位置 1)
x & ~1 // 把 x 末位清零(变成偶数)
x << k // x × 2ᵏ(注意溢出)
x >> k // floor(x / 2ᵏ)
考点总结(CSP-J 初赛选择题)
- 移位
<<>>优先级 高于&^|,但 低于 算术+-。 a << k= \(a \times 2^k\);a >> k= \(\lfloor a / 2^k \rfloor\)。x | 1置最低位为 1;x & (x-1)清最低位的 1。- 秒杀技巧:遇到混合位运算,先按优先级补上括号再动手算,不要凭直觉从左到右。
思考题
int a = 3; 时,cout << (a << 2 + 1); 输出多少?
答案
输出 24。因为 + 的优先级高于 <<,等价于 a << (2+1) = 3 << 3 = 24,而不是 (3<<2)+1 = 13。



