好,这次我不“解释”,我给你一份可以直接背的「位运算·工程级速记教程」。
你就当是口诀 + 模板,以后不再纠结、不再晕。
🧠 位运算工程速记教程(背这个就够)
一、先背这 3 句「生死线」
① 1 << n 是 点亮第 n 位
✔ 表示「有没有」
✘ 不表示「是多少」
② value << n 是 把数塞进第 n 位
✔ 表示「这个字段的值」
✔ 一定能反推
③ 能反推值 ⇒ 不是 1 << n
反推不了 ⇒ 才是
1 << n
二、两大用法(死记)
🟢 用法一:位标志(one-hot)
用途
- 权限
- 开关
- 状态
口诀
「有没有,用 1」
const READ = 1 << 0;
const WRITE = 1 << 1;
const EXEC = 1 << 2;
let state = READ | EXEC;
判断
if (state & READ) { }
❌ 永远不要反推“是第几个”
🔵 用法二:位段字段(value-field)【你现在用的】
用途
- 枚举
- 下标
- 协议
- 0–5 / 0–15 这种值
口诀
「是多少,用 value」
state |= value << offset;
三、你这个项目的「标准模板」(背这个)
1️⃣ 位段划分(16 bit)
TOP = 0; // bit 0~3
BOTTOM = 4; // bit 4~7
LEFT = 8; // bit 8~11
RIGHT = 12; // bit 12~15
2️⃣ 打包(写值)
function pack(top, bottom, left, right) {
return (top << TOP)
| (bottom << BOTTOM)
| (left << LEFT)
| (right << RIGHT);
}
✅ top / bottom / left / right 是 0–15 的数字
3️⃣ 解包(反推)
function unpack(state) {
return {
top: (state >> TOP) & 0b1111,
bottom: (state >> BOTTOM) & 0b1111,
left: (state >> LEFT) & 0b1111,
right: (state >> RIGHT) & 0b1111,
};
}
4️⃣ 真实例子(你现在的)
const state = pack(
0, // 上
5, // 下
0, // 左
0 // 右
);
反推:
const { bottom } = unpack(state);
// bottom === 5
四、为什么你之前 (state >> 4) & 0xff 会懵
❌ 错误认知
1 << (4 + index)
你以为:
“我存了 index”
实际是:
“我点亮了某一位”
✅ 正确认知
index << 4
你说的是:
“我把 index 这个数,写进 bit4~7”
五、判断用哪种的「终极一问」
问自己一句话:
👉「我以后需不需要知道它是几?」
| 答案 | 写法 |
|---|---|
| 需要 | value << n |
| 不需要 | 1 << n |
六、你可以直接贴在项目里的注释(推荐)
/**
* bit protocol:
* bit 0~3 : top (0~15)
* bit 4~7 : bottom (0~15)
* bit 8~11 : left (0~15)
* bit 12~15 : right (0~15)
*
* use value << offset (NOT one-hot)
*/