是什么
-
定义:当相同字长的无符号数赋值给有符号数时,内存中的二进制序列(Bit pattern)完全保持不变,仅仅是编译器解读这串二进制位的规则发生了改变。
-
大白话:数据本身一字未变,变的是“观察它的滤镜”。无符号数滤镜下看都是正数;有符号数滤镜下,只要最高位是 1,就会被解读为负数。
记忆口诀
-
左移 (
<<):不分正负与类型,低位无脑补 0;高位被顶替,符号位可能变(算术溢出)。 -
右移 (
>>):-
无符号数(逻辑右移):高位一律补 0。
-
有符号数(算术右移):保持正负,高位补符号位(正补 0,负补 1),符号位永远不变。
-
-
乘除等价:左移 1 位等价于 ,右移 1 位等价于 。
核心内容
1. 第一道关卡:先看最高位(符号位)是 0 还是 1!
拿到任何一个有符号二进制数(补码),第一步永远是看最高位(符号位):
-
最高位是 0(正数):
-
根本不需要任何取反加 1 操作!
-
原码 = 反码 = 补码(三码合一)。
-
直接按普通的二进制加权求和,算出来的就是正数的十进制真值。
-
(例:
0000 0110最高位为 0,直接按加权算:)
-
-
最高位是 1(负数):
-
这是负数,才需要进行下一步的转换计算!
-
2. 负数补码转换的两种不同操作(严禁混淆)
只有在最高位是 1 时,才存在以下两种不同的处理场景:
| 你的目标 | 适用场景 | 符号位怎么处理? | 数值位怎么处理? | 最终结果 |
|---|---|---|---|---|
| 操作 A:求负数的原码 | 考试要求写出机器数原码 | 符号位保留 1 绝对不动 | 剩下的所有数值位取反加 1 | 得到最高位为 1 的标准原码 |
| 操作 B:求真值(绝对值大小) | 考试要求算十进制是负几 | 连同符号位在内,全部所有位取反加 1 | 得到该负数的正数绝对值,最后手动添个负号 | 直接得出十进制真值 |
-
为什么操作 B 可以“连同符号位全部取反加 1”?
在模 体系中,“全位取反加 1”等价于数学上的求相反数():
负数的相反数就是正数(绝对值),所以符号位的 1 取反后自然变成了 0。
3. 补码的负权重本质与数值映射
不是最高位变成了单纯的“符号标记”,而是==补码最高位被赋予了 的负权重==:
| 位位置(以 8 位为例) | b7(最高位) | b6∼b0 |
|---|---|---|
| 无符号权重 | ||
| 补码(有符号)权重 |
-
本质:状态总数(256 个)不变,只是把无符号数 通过最高位负权重平移映射到了负数区间 。
-
模平移公式:设 位无符号数值为 ,对应有符号真值为 :
-
最高位为 0():
-
最高位为 1():
-
例题
例题 1(正数对照:最高位为 0)
-
题目:8 位补码为
0000 0110,求其原码及十进制真值。 -
分析:最高位是 0,判定为正数,三码合一,无需取反加 1。
-
答案:
-
原码:
0000 0110 -
真值:
-
例题 2(负数计算:8 位 C 语言类型转换)
-
题目:执行以下代码,求
m的十进制真值:
C
unsigned char x = 134; // 1000 0110_2
char m = x;
-
分析:底层位模式为
1000 0110,最高位是 1,判定为负数。 -
答案:
-
方法一(全位取反加 1 求绝对值):
,添负号得 。
-
方法二(符号位不动,数值位取反加 1 求原码):
符号位保留
1,数值位000 0110取反加 1 得111 1010,原码为1111 1010,真值 。 -
方法三(权重代入法):
-
方法四(模公式):
-
例题 3(16 位 MIPS 跳转指令实战)
-
题目:MIPS 指令
bne机器码低 16 位OFFSET为FFFAH,求其真值及跳转字节偏移。 -
分析:,最高位为 1,是负数;MIPS 寻址需左移 2 位(乘 4)。
-
答案:
-
求真值:
-
全位取反加 1:
-
原码验证:符号位保留
1,其余位取反加 1 得原码 ,真值即为 。
-
-
字节偏移:
-
⚠️ 易错点
Warning
看到补码就去“取反加 1” → 最高位是 0 的正数绝对不要动! 正数的原码、反码、补码完全一样。
求原码 vs 求绝对值 傻傻分不清 →
要写出原码:符号位的 1 坚决不动,只动后面的数值位。
想算真值几位数:连同符号位全部取反加 1 算出绝对值,前面补个负号即可。
混淆位模式与解释规则 → 赋值时内存里的 0/1 绝不会变化,改变的只是编译器的读取滤镜。
最高位数值误区 → 补码最高位不是单纯的符号标示,它承载着 的真实负权重。