太好了,你这个问题问在点子上了。
你已经懂 70% 了,现在卡的是那 30% 的“直觉层” 。
我这次不讲抽象概念,只用 「盒子 + 灯」 来把你这一下彻底掰直。
一句话先给你吃颗定心丸
value << n不是“点亮一位”
它是:把一个「小数值」整体搬到某一段 bit 里
一、先建立一个“物理直觉”(很关键)
把 16 bit 想成 16 个小盒子
bit: 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0
────────── ───────── ─────── ───────
RIGHT区 LEFT区 BOTTOM区 TOP区
每一组 4 个盒子,不是用来“亮灯” ,
而是用来 放一个 0–15 的数字。
二、1 << n:你已经完全懂了
1 << 6
意思是:
0000 0000 0100 0000
↑
第 6 位亮了
✔ 它只能表达 “有没有”
✘ 它不能表达 “是几”
三、关键来了:value << n 到底在干嘛?
举一个你现在正在用的真实例子
BOTTOM = 4;
bottomIndex = 5; // 0~5 的选项
第一步:先看 value 本身
bottomIndex = 5
// 二进制:
0101
这不是一个 bit,这是 一个“4 bit 的数” 。
第二步:value << 4 在做什么?
5 << 4
等价于:
原始 5: 0000 0000 0000 0101
左移 4 位: 0000 0000 0101 0000
↑↑↑↑
塞进 bit 4~7
💥 这一步是关键理解点:
不是点亮一个灯
而是把0101这一整坨,
搬到 bit4~7 这 4 个盒子里
四、对比一下你为什么会被搞晕
❌ 错误的心理模型(大多数人都会掉坑)
1 << (BOTTOM + bottomIndex)
你潜意识以为:
“我存了 bottomIndex”
但实际上你干的是:
“点亮了某一盏灯”
✅ 正确模型
bottomIndex << BOTTOM
你说的是:
“我把 bottomIndex 这个数
放进 bottom 这 4 个 bit 的格子里”
五、为什么 value << n 能反推,而 1 << n 不行?
因为信息量不一样
| 写法 | 盒子里内容 | 能反推吗 |
|---|---|---|
1 << 6 | 0001 | ❌ |
5 << 4 | 0101 | ✅ |
六、反推的时候发生了什么?(你刚才卡的地方)
let bottom = (state >> 4) & 0b1111;
拆解含义
1️⃣ state >> 4
👉 把 bottom 区搬回最低位
2️⃣ & 0b1111
👉 只取这 4 个 bit
你拿回来的就是:
0101 → 5
七、一句终极口诀(背这个)
1 << n是“点灯”
value << n是“搬箱子”
或者更工程一点的:
bit flag 用 1
bit field 用 value
八、你现在其实已经会用了(只是差个确认)
你写这个:
let state =
(topIndex << 0) |
(bottomIndex << 4) |
(leftIndex << 8) |
(rightIndex << 12);
这是 100% 正确的协议写法
和 BLE / Zigbee / 米家 / Modbus 是同一套路。