🔷 第三章 运算符与表达式
📄 一句话概括

移位运算符 << >> 把二进制整体搬家:左移 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(负数右移是向下取整,不是向零),这就是为什么"负数别拿移位当除法"。

五、常见误区

  1. "左移补符号位"——左移永远补 0。补符号位的是右移。
  2. "x << n 对浮点也能用"——不能,<< 只认整数(浮点在内存里的排布完全不同)。
  3. "a << 2 + 1 是 (a << 2) + 1"——错了,+ 优先级高于移位,实际是 a << 3。写移位表达式请加括号:(a << 2) + 1。
  4. "移位就是乘除,随便替换"——只对 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)。

相关笔记