六个操作符:位运算的完整词汇表
位运算直接操作二进制位,六个基本操作各有明确的语义。AND(&):两位都 1 才 1——用途是「提取」(掩码:x & 0b1111 取低 4 位)与「检测」(x & flag 非 0 即有此标志)。OR(|):有 1 则 1——用途是「设置」(x | flag 打开标志位)。XOR(^):不同为 1——用途是「翻转」(x ^ flag 切换标志位)与「无第三方交换变量」(a^=b; b^=a; a^=b——炫技多于实用,但 XOR 的可逆性是真数学)。NOT(~):按位取反。左移(<<):x << n 等价 ×2^n(无溢出前提)。右移(>>):等价 ÷2^n——算术右移保留符号位(负数右移仍是负数,这是有符号数的细节)。
一个必须内化的概念:位掩码(bitmask)——把一组布尔状态打包进一个整数:flags = READ | WRITE(设置),flags & WRITE(检查),flags & ~WRITE(清除,AND 上取反)。32 位整数装 32 个布尔,内存是布尔数组的 1/32,且整组状态的存取、比较、传输都是一次 CPU 操作。
位存状态:权限系统与特性开关的标准实现
权限系统是位掩码的经典主场:Unix 文件权限(rwxr-xr-x 正是 9 个二进制位,755 是八进制写法)、Linux 的文件属性位、数据库的标志列。设计模式:const READ=1, WRITE=2, EXEC=4(2 的幂)、权限的组合与拆解全部是位运算、数据库里一列 permissions INT 就能存任意组合。特性开关(feature flags)同理:一个位段表示「哪些功能对哪些用户开启」,按位与判断——比布尔列的扩展性好(加新特性不迁移表结构,占用新位即可)。位图(bitmap)是大规模版本:1 亿用户的「今日签到」状态只需 12.5MB 的位图——bitmap[pos >> 3] & (1 << (pos & 7)) 定位到具体位;Redis 的 SETBIT/BITCOUNT 就是这个结构的工业实现(本库布隆过滤器篇的位数组也是位图亲戚)。
网络与协议里的位运算:子网掩码与协议头
IP 子网划分是位运算最经典的日常应用:192.168.1.100/24 的 /24 表示前 24 位是网络号——判断两个 IP 是否同网段 = (ip1 & mask) == (ip2 & mask)(按位与直接提取网络号)。子网掩码 255.255.255.0 的二进制是 24 个 1 跟 8 个 0——「掩码」这个名字就是字面意义。协议头的解析同样是位运算:TCP 头里各字段挤在同一个 32 位字里(源端口 16 位 + 一堆标志位),解析协议就是一连串的移位与掩码——读到本章,Wireshark 里的 hex dump 从天书变成说明书。
性能优化的是与非:哪些值得写、哪些是负优化
值得的位运算。奇偶与整除判断:x & 1(比 x % 2 快,编译器其实会自动做——真正的价值在可读性约定内统一写法)。交换与取反的惯用法:~x + 1 = -x(补码的礼物)。判断 2 的幂:x & (x-1) == 0(一行判断,标准面试题但也是真实技巧)。集合运算:两个位掩码的 AND/OR 就是无交集/并集——比集合库快一个量级。不值得的「负优化」:用移位替代乘除法的现代实践(编译器几十年来都做这个优化,手写只会降低可读性);用 XOR 交换变量(寄存器时代无收益且有坑);「看起来很酷」的位压缩逻辑(可维护性税)。判断标准一句话:位运算该用在「数据本身是位/标志集合」的场景(权限、状态、协议、位图),而不是用在「数学计算的微观替换」——前者是正确的设计,后者是时代的眼泪。
位运算的进阶应用:状态机、协议与算法里的位技巧
位运算的进阶应用有三个值得单独看的高价值场景。场景一:位状态机。用位段表示「对象的状态组合」——订单状态(已支付 0b0001、已发货 0b0010、已收货 0b0100、已评价 0b1000):状态检查 status & SHIPPED、状态迁移用位或叠加——与「枚举 + 集合」的实现相比,位段在存储(一列 INT)、传输(一个数字)、比较(一次运算)上全面占优,代价是可读性(用常量与注释补)。场景二:协议解析的位段。网络协议(IP 头的版本+IHL 共用一个字节、TCP 的标志位挤一个字节)、文件格式(PNG 的位深度字段)——读协议文档 + 位运算是同一套肌肉:(byte >> 4) & 0x0F 取高 4 位。场景三:算法题与工程里的位技巧。x & (x-1) 消去最低位的 1(统计 1 的个数 Brian Kernighan 算法——比逐位扫快)、x & (-x) 取最低位的 1(树状数组 Fenwick Tree 的核心操作——竞赛与工业算法都在用)、集合的子集枚举(sub = (sub-1) & mask)。位运算进阶的边界提醒:这些技巧的适用前提是「数据本身就是位语义」(标志、状态、集合成员、协议字段)——脱离这个前提的位技巧是负优化(正文的原则在进阶场景同样有效)。
位与浮点:一个整数装下两个数的小魔法
位运算与浮点数(本库上一篇)在工程里有一个漂亮的交点:用位操作直接访问浮点的内部表示。原理:float 的位模式(IEEE 754)可以 reinterpret 成整数——快速开方倒数算法(著名的 Quake III 神秘常数 0x5f3759df)就是「把 float 当整数做近似运算」的历史名场面。现代的实用变体:快速取整(大数偏移法——利用 double 的整数精度区做截断)、NaN 的快速检测(位模式比较)、比较浮点为正负零(位模式区分 +0/−0)。另一个交点是「位段打包」:把多个小数值(年月日时分秒、坐标分块)打包进一个整数存储与传输(6 个字段的日期时间打包成一个 64 位整数)——解包用移位掩码,存储与索引效率高(数据库里一列搞定多维排序)。这个交点的元意义:位运算与浮点数是「同一位世界的两种解释」——理解了 IEEE 754 的位布局,浮点就不再是黑盒;理解了位操作,浮点的某些「玄学行为」(−0、NaN 比较、精度边界)都有了位级别的解释——两个主题互为注脚。
位运算的实战限制:为什么现代代码里位技巧越来越少
位运算(正文)的实战边界需要诚实的反面视角:为什么现代应用代码里位技巧越来越少。原因一:编译器与运行时的自动化。乘除的移位优化、奇偶与对齐判断——编译器几十年前就在做,手写位版本不会更快(可读性反而降)。原因二:抽象层的普遍上移。应用开发的语言(Python/JS/Go)把位运算场景封装成了库(权限用位标志库或枚举集合、协议用现成的解析库)——位运算正在从应用层下沉到基础设施层(数据库引擎、网络栈、编解码库的作者仍是位运算的重度用户)。原因三:性能优化的重心转移。现代性能瓶颈在内存访问模式、网络、与算法复杂度——位级微优化(省几个周期)在缓存 miss 面前是零头的零头。位运算仍然不可替代的阵地:协议与格式解析(每层都要重新发明——这是「通用知识」而非「可封装的库」)、位图与大规模标志(Redis 位操作、Roaring Bitmap——数据库与风控的工业级位图)、以及系统编程的日常(驱动、内核、嵌入式——那里没有「抽象层」,位就是硬件的接口)。这一节的元结论:学位运算的意义随开发层级而变——应用层学语义(读懂标志位与掩码代码),系统层练手感(位是你的母语)——知道自己的层在哪,决定练到多深。
位运算的进阶应用:状态机、协议与算法里的位技巧
位运算的进阶应用有三个值得单独看的高价值场景。场景一:位状态机。用位段表示「对象的状态组合」——订单状态(已支付 0b0001、已发货 0b0010、已收货 0b0100、已评价 0b1000):状态检查 status & SHIPPED、状态迁移用位或叠加——与「枚举 + 集合」的实现相比,位段在存储(一列 INT)、传输(一个数字)、比较(一次运算)上全面占优,代价是可读性(用常量与注释补)。场景二:协议解析的位段。网络协议(IP 头的版本+IHL 共用一个字节、TCP 的标志位挤一个字节)、文件格式(PNG 的位深度字段)——读协议文档 + 位运算是同一套肌肉:(byte >> 4) & 0x0F 取高 4 位。场景三:算法题与工程里的位技巧。x & (x-1) 消去最低位的 1(统计 1 的个数 Brian Kernighan 算法——比逐位扫快)、x & (-x) 取最低位的 1(树状数组 Fenwick Tree 的核心操作——竞赛与工业算法都在用)、集合的子集枚举(sub = (sub-1) & mask)。位运算进阶的边界提醒:这些技巧的适用前提是「数据本身就是位语义」(标志、状态、集合成员、协议字段)——脱离这个前提的位技巧是负优化(正文的原则在进阶场景同样有效)。
位运算的学习路径与练习资源
位运算(正文)的学习路径收尾,四步进阶与练习建议。第一步:建立二进制直觉——日常用二进制视角看 0–255 的小数字(255 = 8 个 1、128 = 最高位 1),熟练到「看见 0xFF 知道是全 1」。第二步:掌握六大操作与三大惯用法——掩码提取、标志设置/清除/检测、x&(x-1) 家族(消位、判 2 的幂、取最低位)——每一项手写十遍以内化。第三步:做专题练习——LeetCode 的位运算标签题(只出现一次的数字系列、位计数、子集枚举——题量十来道即可建立手感),以及读一段真实代码(Redis 的 SDS 标志位、Linux 权限位、任何协议解析代码)。第四步:在工程里识别「该用位」的场景——code review 时看到「一组布尔字段」想到位段、看到协议文档想到位解析、看到集合运算想到掩码——位运算的掌握标志,是「把数据建模成位」的眼光,而非背指令。四步走完,位运算就从「考试知识」变成「建模工具」——它在你眼里的样子,会从十六进制的乱码变成清晰的结构图。
小结
位运算六操作符各有语义:AND 提取与检测、OR 设置、XOR 翻转、移位乘除。位掩码把布尔集合打包进整数——权限系统(Unix 755 的九个位)、特性开关、位图(1 亿签到 12.5MB)是三大主场,Redis 的位操作与布隆过滤器是它的工业后代。网络世界的子网判断与协议解析全是位运算的原生领地。性能优化的判断标准:数据本身是位集合时用位运算是好设计,替代数学运算是负优化——位运算的最高境界不是炫技,是把「一组开关」诚实地建模成它本来的样子:一个整数。
读者留言
COMMENTS 暂无还没有留言,来说第一句?