位移运算怎么算:左移、右移、无符号右移与位运算优化
讲清左移右移和无符号右移三种位移运算怎么算,左移 1 位等于乘 2、右移等于除 2 的原理,以及怎么用二进制和十六进制读结果,顺带聊位运算优化和权限标志位。
位移运算怎么算:左移、右移、无符号右移与位运算优化
写底层代码的人迟早会撞上 <<、>>、>>> 这三个符号。它们看着像在打字游戏里乱按,实际上每一个都在干一件很具体的事:把一串二进制位整体往某个方向挪几格。挪法不同,结果天差地别。我把这三种位移运算拆开讲一遍,再说说它们在乘除、权限标志和底层编程里到底有什么用。想边读边验算,可以打开 位移运算计算器,把数填进去看位是怎么动的。
三种位移到底在挪什么
位移运算的对象不是十进制数字,而是它背后的二进制位。
- 左移
value << n:所有位往左挪 n 格,右边空出来的位补 0,左边挪出去的位丢掉。 - 算术右移
value >> n:所有位往右挪 n 格,左边空出来的高位补符号位,这样负数还是负数。 - 逻辑右移
value >>> n:也往右挪,但左边高位一律补 0,完全不管符号,把数当成纯粹的无符号位模式。
差别最大的地方在右移补什么。以 8 位的 -8 为例,它的位模式是 11111000。算术右移 1 位得到 11111100,也就是 -4;逻辑右移 1 位得到 01111100,也就是 124。同一个输入,两种右移,一个是负数一个是大正数。原始无符号数据(字节、颜色通道、标志位)用逻辑右移,有符号整数用算术右移,选错就会埋下一个很难发现的 bug。
左移等于乘 2,右移等于除 2
这是位移运算最实用的一条直觉。把每一位往左挪一格,权重为 1 的位变成权重 2,权重 2 的变成 4,数值正好翻倍。所以左移 n 位就等于乘以 2 的 n 次方。
来一个真实的输入输出:5 << 2 = 20。5 的二进制是 00000101,往左挪两格变成 00010100,正好是 20,也就是 5 乘以 4。同理 5 << 1 = 10。
反过来,算术右移就是向下取整除以 2。20 >> 1 = 10,256 >> 2 = 64。要注意它是向负无穷取整,不是向零截断:-7 >> 1 = -4 而不是 -3,因为 floor(-3.5) 是 -4。把 C 或 JavaScript 的移位代码移植到向零截断的语言时,这个负数差一位是经典坑。
为什么底层这么爱用移位代乘除?在没有硬件除法器的单片机上,x << 3 算 x 乘 8 只要一个时钟周期,而一次真正的乘法或除法可能要几十个周期。位运算优化的本质就是把乘除 2 的幂换成移位。
位宽和溢出:别忘了挑 8/16/32
位移有一个前提:你在多少位的空间里挪。每个位宽的位槽数量固定,左移把位推过最高位时,这些高位直接被丢掉。
8 位下 255 << 1 不会得到 510。11111111 往左挪一格变成 11111110,高位的 1 掉出去了,结果是 254 的无符号读法,而在有符号读法下它是 -2。同样的 200 << 1 也不会变成 400,而是回绕。换到 16 位或 32 位才有足够余量。读结果前一定要把位宽设成跟目标寄存器一致,否则你算的根本不是芯片会跑的那个数。
用二进制和十六进制读结果
十进制能告诉你数值,但看不清位移到底发生了什么。把结果同时摊成二进制和十六进制,位的流动就一目了然。二进制按 4 位一组对齐,一眼能看出一边补进零、另一边的位掉出去;十六进制则适合跟寄存器手册对照,因为手册基本都用 0x 写位段。比如 32 位下 -1 是 0xFFFFFFFF,逻辑右移 1 位变成 0x7FFFFFFF,也就是 2147483647,而算术右移 1 位还是 -1。十六进制一摆出来,这种符号差异立刻看得清。
权限标志位与底层编程
位移运算在工程里最常见的两个落点是标志位和字段拆包。
功能开关常以单个位存在:1 << 0、1 << 1、1 << 2,每个左移把唯一的那个置位推到不同位置。同事在权限枚举里写 1 << 5,你想确认它是 32 还是 64,算一下就知道是 32。这里有个高频错误:位的位置从 0 开始数,第一个标志是 1 << 0 而不是 1 << 1,差一位会让每个掩码都翻倍。
字段拆包则常见于颜色和协议头。一个 32 位颜色把红绿蓝透明四个 8 位通道挤在一起,读红色通道就右移 24 位再取掩码,组装颜色就把每个通道左移到位(红 << 24、绿 << 16、蓝 << 8)。网络头同理,4 位版本号加 12 位长度塞进一个字,右移加掩码就能逐字段取出来。这类操作经常跟按位与或异或配合,标志位的设置、清除、检测离不开 & | ^,可以配合 按位与或异或计算器 一起验算。
我自己怎么用
我调一段图像解码代码时,从一个 32 位像素里取 alpha 通道,本该 >>> 24 却写成了 >> 24,正常图片看不出问题,直到遇到一张 alpha 高位置 1 的图,算术右移把符号位灌了进来,整个通道值全错。当时盯着十进制怎么也想不通,把那个值丢进位移计算器,二进制一摆,补进来的一排 1 立刻露馅。从那以后,只要碰到无符号数据的右移,我都先在工具里跑一遍位模式再写进代码,省下的排查时间远比多点两下鼠标值钱。
位移运算说穿了就是位往哪边挪、空位补什么、超出位宽怎么办这三件事。把它们想清楚,左移乘 2、右移除 2、标志位拼装这些底层套路就都顺了。
Made by Toolora · Updated 2026-06-13