跳到主要内容

位运算入门:按位与、或、异或、取反与移位怎么用

用一篇文章讲清按位与或异或取反与移位的真值表和实际用途,从权限标志位到掩码再到乘 2 优化,并说清它和逻辑运算的区别,看完就能上手算。

发布于 作者 李雷
#位运算 #按位运算 #二进制 #开发工具

位运算入门:按位与、或、异或、取反与移位怎么用

很多人写了几年代码,见到 &|^~<<>> 还是要愣一下。它们不像加减乘除那样直观,因为它们不是在数值层面运算,而是把整数拆成一排二进制位,逐位处理。一旦你把每个运算的真值表记住,这些符号就从天书变成了趁手的工具。下面我把五种位运算讲清楚,再说它和逻辑运算的区别,以及它在真实代码里到底拿来干什么。

五种运算的真值表

位运算的全部规则就藏在几张小表里。按位与 &:两位都是 1 才得 1,否则得 0。按位或 |:只要有一位是 1 就得 1,两位都是 0 才得 0。按位异或 ^:两位不同得 1,相同得 0。

| A | B | A&B | A\|B | A^B | |---|---|-----|------|-----| | 0 | 0 | 0 | 0 | 0 | | 0 | 1 | 0 | 1 | 1 | | 1 | 0 | 0 | 1 | 1 | | 1 | 1 | 1 | 1 | 0 |

取反 ~ 只作用于一个值,把每一位都翻转,1 变 0、0 变 1。移位也只作用于一个值:左移 << 把所有位往高位挪、低位补 0;右移 >> 往低位挪、丢掉末尾。把这几条记牢,后面的一切都是推导。

一个动手就懂的例子

抽象的表不如算一遍。拿 5 和 3:5 的二进制是 101,3 是 011。

做按位与,逐列看:最高位 1 与 0 得 0,中间位 0 与 1 得 0,最低位 1 与 1 得 1,结果是 001,也就是十进制 1。所以 5 & 3 = 1

换成按位或:每一列只要有 1 就得 1,三列分别得 1、1、1,结果是 111,也就是 5 | 3 = 7

再看异或:逐列比不同,最高位 1 与 0 不同得 1,中间位 0 与 1 不同得 1,最低位 1 与 1 相同得 0,结果 110,即 5 ^ 3 = 6。这三道题一起算完,真值表就刻进脑子了。如果你想边输边看二进制对照,可以打开 位运算计算器,它会把 A、B 和结果逐列对齐,哪几位翻转了一眼就看清。

位运算和逻辑运算不是一回事

这是新手最容易踩的坑。&&& 长得像,干的活完全不同。逻辑与 && 看的是整个值的真假:它把两个操作数各自当成一个布尔结果,只回答真或假。按位与 & 不管真假,它钻进二进制内部,一位一位地算,返回的还是一个整数。

举例:5 && 3 在大多数语言里得到 3 或 true,因为两个数都非零、都算真;而 5 & 3 得到 1,是逐位运算的结果。异或也一样,逻辑上没有 ^^ 这种短路运算符,^ 永远是按位的。简单记:带两个符号的(&&||)是逻辑判断、会短路;带一个符号的(&|^)是逐位计算、不短路。

标志位与掩码:位运算最常见的活

我自己写嵌入式那阵子,几乎每天都在和寄存器打交道。一个控制寄存器可能第 3 位管中断使能、第 4 到 6 位是分频系数,把这些状态塞进一个整数里最省空间,而读写它们靠的就是位运算。

想读某一位,用按位与配一个掩码:value & 0x08 只保留第 3 位,非零就说明开着。想置位,用按位或:value | 0x08 把第 3 位打开,其余位不动。想翻转,用按位异或:value ^ 0x08,开的关掉、关的打开。想清掉某一位,先取反掩码再按位与:value & ~0x08。权限系统也是同一套路,把读、写、执行各占一位,一个整数就表达了一组权限,Linux 文件权限的数字背后正是这个机制,想换算具体数字可以看 Linux 权限计算器

移位:用位运算做乘除优化

左移有个漂亮的性质:左移一位等于乘以 2。因为每一位往高位挪一格,数值正好翻倍。所以 3 << 4 等于 48,和 3 乘 16 一模一样;右移则是除以 2 的幂并丢掉余数,256 >> 2 等于 64。

早年编译器不够聪明时,程序员会手写移位代替乘除来提速,如今编译器大多会自动优化,但移位在打包字段时依旧不可替代:把一个颜色的红、绿、蓝三个分量塞进一个整数,就是把每个分量左移到对应位置再按位或合并,取回来时用按位与加右移。这种紧凑表示在图形、网络协议里随处可见。

取反为什么要先定位宽

取反 ~ 有个容易忽略的细节:它翻转每一位,但到底有多少位,取决于数据类型。纯数学上整数有无穷多前导位,翻转后会变成负数,这就是为什么 ~0 在很多语言里是 -1。如果你想要的是 8 位下的全 1,也就是 255,就得先框定一个 8、16、32 或 64 位的窗口。无符号右移同理,它从这个窗口顶端补 0,而不是补符号位。算这类题时盯着十进制、十六进制、二进制三种形式一起跳,理解会快很多。

位运算说到底没有魔法,就是把整数还原成一排灯,逐个开关。记住这几张真值表,分清它和逻辑运算的边界,你会发现标志位、掩码、移位优化这些原本绕口的东西,其实都顺理成章。


Made by Toolora · Updated 2026-06-13