移位运算:一个让数字“搬家”的神奇操作,你真的懂了吗?
左移右移,移的不是寂寞,是数字的灵魂。
在计算机组成原理、C语言编程甚至考研408中,有一个看似简单却暗藏玄机的知识点——定点数的移位运算。很多同学觉得它太基础,结果考试一考就错,编程一用就崩。
今天,我们就用一篇文章,把移位运算彻底讲清楚。文末还有两道真题,看看你能做对几道?💪
🧭 一、移位运算的两大门派
移位运算分为两大门派:逻辑移位 与 算术移位。
它们的区别,就在于对待符号位的态度。
🔷 逻辑移位 —— 一视同仁,全部补0
逻辑移位不关心数字的符号,只把二进制位当成普通的0和1来处理。
-
逻辑左移:高位丢弃,低位补0
比如 0110 1101 左移1位 → 1101 1010 -
逻辑右移:低位丢弃,高位补0
比如 0110 1101 右移1位 → 0011 0110
✅ 逻辑左移和逻辑右移的“低位补0/高位补0”看起来对称,效果其实一样——都是往空位塞0。
🔶 算术移位 —— 符号位是“VIP”,必须特殊照顾
算术移位专门用于带符号整数(补码表示)。它的规则是:符号位不动,其它位移动。
-
算术左移:高位丢弃,低位补0(和逻辑左移操作一样,但溢出判断不同)
-
算术右移:低位丢弃,高位补符号位(关键区别!)
比如负数 1000 1101(补码)算数右移1位 → 1100 0110
高位补的是原来的符号位1,保证负数右移后还是负数。
🧮 二、移位运算与乘除法的“等价关系”(很多同学死在这)
📌 对无符号整数
-
逻辑左移1位 ≈ 乘以2
( 0000 0011 ) 左移1位 = 0000 0110 = 6,没错吧? -
⚠️ 但是! 如果高位丢弃的是1,说明结果已经超出表示范围,发生溢出。
比如 4位下 1001 (9) 左移1位 → 0010 (2),完全不对,因为9×2=18,4位装不下。
📌 对带符号整数(补码)
-
算术左移1位 ≈ 乘以2
-
正数:没什么问题
-
负数:注意符号位变化!
1110(-2)左移1位 → 1100(-4),正确。
但如果左移后符号位变了(比如正数变负数),就是溢出。
-
-
算术右移1位 ≈ 除以2(向下取整)
-
1110(-2)右移1位 → 1111(-1),-2÷2 = -1,ok。
-
1101(-3)右移1位 → 1110(-2),-3÷2 = -1.5,取整为-2(向负无穷取整),符合补码右移规则。
-
✅ 所以结论一张表:
|
无符号逻辑左移 |
×2 |
高位移出1 → 溢出 |
|
无符号逻辑右移 |
÷2 |
低位移出1 → 丢失精度(向下取整) |
|
带符号算术左移 |
×2 |
符号位改变 → 溢出 |
|
带符号算术右移 |
÷2(向负无穷取整) |
精度丢失(奇数的负数更明显) |
💡 三、常考技巧:用移位实现快速乘除
在底层代码优化中,编译器经常用移位代替乘除法,因为移位比乘除快几十倍。
-
左移 r 位 ⇔ 乘以 (2^r)
a << 3 等价于 a * 8 -
右移 r 位 ⇔ 除以 (2^r)(注意符号位影响)
a >> 2 等价于 a / 4(仅对正数或特殊场景)
🎯 考法:给你一个表达式 x * 15,让你用移位和加减实现。
答案:(x << 4) – x (16x – x = 15x)
📝 四、真题挑战(试试你能对几道?)
🔸 题目1(408 2018年统考真题)
某机器字长8位,采用补码表示。若变量x的补码为 1111 1000,则算术右移1位后得到的补码为( )
A. 1111 1100
B. 0111 1100
C. 1111 0100
D. 0111 0100
📌 答案
解析
算术右移:低位丢弃,高位补符号位。原符号位为1,所以高位补1。
1111 1000 右移1位 → 低位移出0,高位补1: 1111 1100。
选 A。
🔸 题目2(某高校期末真题)
以下关于C语言中移位运算的说法,正确的是( )
① 对无符号整数执行逻辑右移,相当于除以2并向下取整。
② 对有符号负数执行算术左移,若符号位改变,则发生溢出。
③ -3 >> 1 在绝大多数编译器中结果等于 -2。
④ (unsigned int)-1 >> 1 的结果是 0x7FFFFFFF(假设32位)。
A. ①②③
B. ②③④
C. ①③④
D. ①②③④
📌 答案
解析
① 正确,逻辑右移对无符号数就是整除2向下取整。
② 正确,左移后符号位变化说明数值范围超出。
③ 正确,C语言中对有符号整数的右移是算术右移,-3的补码右移得-2。
④ 正确,-1的unsigned表示全1,右移1位高位补0,变成 0111… 即 0x7FFFFFFF。
全部正确,选 D。
🎯 总结
|
逻辑左移 |
高位丢弃,低位补0 |
无符号×2 |
|
逻辑右移 |
低位丢弃,高位补0 |
无符号÷2 |
|
算术左移 |
高位丢弃,低位补0 |
有符号×2(注意溢出) |
|
算术右移 |
低位丢弃,高位补符号位 |
有符号÷2(向负无穷取整) |
移位运算虽小,却是理解计算机底层运算、优化代码、应对笔试面试的必备基础。
下次再看到 << 或 >>,别只当成简单的“移一下”,想想它背后的乘法除法、溢出陷阱、符号位处理——你就会比别人更进一层。🚀
📌 如果你觉得有用,欢迎点赞、在看、转发给正在备考或学计算机的朋友~
评论区留下你对移位运算的疑问,或者分享一道你遇到的移位题,一起讨论!


