📄 一句话概括
移位运算符 << >> 把二进制整体搬家:左移 n 位 = ×2 的 n 次方,右移 n 位 = ÷2 的 n 次方(取整)。乘除 2 的幂最快的写法就是它——理解了"搬家补 0",就不用背公式。
一、移位就是"二进制整体搬家"
回看 2.2.1 十进制:38 往左挪一位变 380(×10)。二进制同理,只不过一位是 ×2 不是 ×10:
6 = 0b0110
6 << 1 → 0b1100 = 12 (×2)
6 << 3 → 0b0110000 = 48(×2×2×2)
左移 <<:整体向左搬 n 格,低位空出来的补 0,高位挤出去的丢掉(int 只有 32 格,挤没了就是溢出——2.3.3 的老话题)。
右移 >>:整体向右搬 n 格,高位空出来的补符号位(正数补 0、负数补 1,保持正负号不变),低位挤掉的丢掉:
15 = 0b1111
15 >> 1 → 0b0111 = 7 (÷2,余数丢了)
15 >> 2 → 0b0011 = 3 (÷4)
二、一句话总结:移位 = 乘除 2 的幂
| 表达式 | 等价于 | 例子 |
|---|---|---|
x << n |
x × 2ⁿ |
3 << 4 = 48 |
x >> n |
x ÷ 2ⁿ(取整) |
100 >> 3 = 12 |
右移丢余数:15 >> 1 = 7 不是 7.5——挤掉的低位就是余数,跟整数除法一个脾气。其实 x >> n 和 x / 2ⁿ 对正数完全等价。
为什么用移位不用乘除? CPU 算移位只要"挪格子"一个动作,算乘除要做完整乘法——历史上移位快得多。今天的编译器早会把 x * 8 自动优化成 x << 3,所以可读性优先、不必强行替换;但读别人代码时必须认识:1 << 10 就是 1024。
三、常见用途
// 1. 造掩码(配合 3.1.5 的位运算)
int mask = 1 << 3; // 0b1000:第 3 位是 1 的掩码
int n = 13; // 0b1101
cout << (n & mask) << endl; // 8(第 3 位是 1)
// 2. 快速算 2 的幂
cout << (1 << 10) << endl; // 1024(背:1 左移 10 位)
// 3. 拆字节
int color = 0xFF8000; // 假设一个颜色值
int r = color >> 16; // 高 8 位 = 0xFF = 255
int g = (color >> 8) & 0xFF; // 中 8 位 = 0x80 = 128
第 3 个用途是经典套路:右移把想要的段搬到最低处,再 & 0xFF 筛出来——"搬 + 筛"两连招。
四、动手 Demo:教材实例03(左移运算)思路复现
#include <iostream>
using namespace std;
int main() {
int x = 3;
cout << (x << 1) << endl; // 6 = 3×2
cout << (x << 4) << endl; // 48 = 3×16
cout << (1 << 10) << endl; // 1024
cout << (100 >> 2) << endl; // 25 = 100÷4
cout << (15 >> 1) << endl; // 7 (余数丢了)
// 移位 vs 乘除:殊途同归
cout << (x * 16) << " " << (x << 4) << endl; // 48 48
return 0;
}
看到什么算成功:6 48 1024 25 7 48 48。重点体会 1 << 10 = 1024——1 后面跟 10 个 0,正是"二进制里的 1、10、100"。
30 秒实验:输出 x << 4 和 x * 16,两者相等;再试试 (-7) >> 1——输出 -4(负数右移是向下取整,不是向零),这就是为什么"负数别拿移位当除法"。
五、常见误区
- "左移补符号位"——左移永远补 0。补符号位的是右移。
- "
x << n对浮点也能用"——不能,<<只认整数(浮点在内存里的排布完全不同)。 - "
a << 2 + 1是(a << 2) + 1"——错了,+优先级高于移位,实际是a << 3。写移位表达式请加括号:(a << 2) + 1。 - "移位就是乘除,随便替换"——只对 2 的幂成立;
x << n遇到 n≥32 或溢出结果是未定义的。理解原理、阅读时认识它,就够本阶段用。
自测四问(点开对答案)
1. `5 << 3` 等于多少?——`40`(5×8)。 2. `20 >> 2` 等于多少?——`5`(20÷4)。 3. `1 << 6` 等于多少?——`64`。 4. `-6 >> 1` 的空位补什么?——补符号位 1,结果仍是负数(-3)。- ☐ 3.1.7 sizeof运算符(下一节)