Appearance
定点数的移位运算
考情分析
移位运算在 2012、2017、2018 年的真题中以选择题出现。常与乘除法结合考查,或考查算术移位与逻辑移位的区别。
移位与乘除的关系
对于二进制整数:
- 左移一位(未溢出时)
乘以 2 - 右移一位(忽略移出位)
除以 2
没有乘/除运算电路时,可以用"加法 + 移位"组合实现乘除运算。
逻辑移位
逻辑移位将操作数视为无符号整数。
| 操作 | 规则 |
|---|---|
| 逻辑左移 | 高位移出,低位补 0 |
| 逻辑右移 | 低位移出,高位补 0 |
示例(4 位无符号数):
| 原始值 | 操作 | 结果 | 说明 |
|---|---|---|---|
0001(1) | 左移 1 位 | 0010(2) | |
0001(1) | 右移 1 位 | 0000(0) | |
1000(8) | 左移 1 位 | 0000(0) | 溢出( |
逻辑左移时,若移出的高位为 1,则发生溢出。
算术移位
算术移位将操作数视为有符号整数(补码)。
| 操作 | 规则 |
|---|---|
| 算术左移 | 高位移出,低位补 0。若移出位与原符号位不同,发生溢出 |
| 算术右移 | 低位移出,高位补符号位 |
补码算术移位规则总结:
| 移位方向 | 正数(符号位 0) | 负数(符号位 1) |
|---|---|---|
| 左移 | 低位补 0 | 低位补 0 |
| 右移 | 高位补 0 | 高位补 1 |
本质上:左移时两者都补 0;右移时补的是符号位的值。
示例(4 位补码):
| 原始值 | 真值 | 操作 | 结果 | 真值 | 说明 |
|---|---|---|---|---|---|
0010 | +2 | 左移 1 | 0100 | +4 | 正常 |
0100 | +4 | 左移 1 | 1000 | 溢出(符号位改变) | |
1001 | 左移 1 | 0010 | +2 | 溢出( | |
1001 | 右移 1 | 1100 | 高位补 1,精度损失( | ||
0110 | +6 | 右移 1 | 0011 | +3 | 高位补 0 |
算术右移的结果是向下取整(向负无穷方向),而非向零截断。
算术移位 vs 逻辑移位
| 对比项 | 算术移位 | 逻辑移位 |
|---|---|---|
| 操作数类型 | 有符号数(补码) | 无符号数 |
| 左移补位 | 补 0 | 补 0 |
| 右移补位 | 补符号位 | 补 0 |
| 溢出判断 | 左移后符号位改变则溢出 | 左移移出 1 则溢出 |
| 对应 C 操作 | 有符号数的 >> | 无符号数的 >>(C 中 << 两者相同) |
在 x86 指令中:shl/shr 为逻辑移位,sal/sar 为算术移位。左移时 shl 和 sal 行为完全相同。
循环移位
移出的位填到另一端,不丢失任何位。
| 操作 | 规则 |
|---|---|
| 不带进位循环左移 | 最高位移到最低位,同时送入 CF |
| 不带进位循环右移 | 最低位移到最高位,同时送入 CF |
| 带进位循环左移 | 最高位 → CF → 最低位(CF 参与循环) |
| 带进位循环右移 | 最低位 → CF → 最高位(CF 参与循环) |
循环移位适用于将数据的高位和低位对调,或在多字节数据间传递进位。
示例(8 位,不带进位循环左移):
10110011 → 循环左移 1 位 → 01100111
最高位的 1 被移到最低位。
考点清单
- 逻辑移位:无符号数,左右移空位均补 0
- 算术移位:有符号数(补码),左移补 0,右移补符号位
- 算术左移溢出判定:移出位与符号位不同则溢出
- 补码算术右移是向下取整(向负无穷),不是向零截断
- shl/shr = 逻辑移位,sal/sar = 算术移位
- 循环移位不丢失位,分带进位和不带进位两种