c语言学习-原码反码补码

原码、反码、补码为什么出现

1. 原码的历史背景

计算机中数值都是以二进制形式存储的,如果要进行计算,会用二进制形式进行,一般整数类型都有符号,则会用最高位1表示负号,最高位0表示正号。

有符号的char类型中的1,用二进制表示就是 0000 0001,有符号的char类型中的-1,用二进制表示就是 1000 0001。

其中0000 0001为1的原码 、1000 0001为-1的原码

如果此时计算机也计算1-1,转换为1+(-1)

原码计算加法过程如下

  0000 0001
  1000 0001
+ ------------ 
  1000 0010

计算结果的原码为 1000 0010,按照带符号的规定,则十进制值为-2。明显是错误的结果。为什么产生这个原因呢?首先结果为负值是最高位的符号位参加了运算,导致结果为负值,其次值为2表示负数直接用原码和正数相加,值会越来越大,因此引入了反码。

2. 反码的历史背景

直接用原码逻辑的话,正数和负数相加,有效位的值会越来越大,因此需要规避这种情况,让值变小,因此引入反码。

正数的反码是原码本身,负数的反码是符号位不变,其余为取反。

1 的原码是 0000 0001,反码也是 0000 0001。
-1的原码是 1000 0001,反码是 1111 1110。

反码计算加法的过程如下

  0000 0001
  1111 1110
+ ------------ 
  1111 1111

反码的结果为1111 1111,则将反码转为原码为 1000 0000,对应的十进制值为-0,但是char中的原码0000 0000表示为+0,计算机为了不浪费空间,因此规定只用一个来表示真正的0,那就是 0000 0000,因此1+(-1)的原码应该是 0000 0000,而不是 1000 0000,为了解决这个问题,引入了补码概念

3. 补码的历史背景

正数的补码是原码
负数的补码是反码+1,如果超过位数,则按照char最大8位,截取最后的8位,为最终补码。

1的原码是 0000 0001,反码是 0000 0001,补码是 0000 0001
-1的原码是 1000 0001,反码是 1111 1110。补码是 1111 1111

补码计算加法的过程如下

  0000 0001
  1111 1111
+ ------------ 
1 0000 0000

补码的结果是 1 0000 0000,截取后补码为 0000 0000,对应的反码是 0000 0000,对应的原码也是 0000 0000。

4. -128的故事

原码 0000 0000 光荣的表示为0了,之前 char类型能够表示数值的范围为 1111 1111 ~ 0111 1111,对应的十进制为 -127~127,中间的0我们知道可以用 0000 0000来表示,那么多出来的 1000 0000 不就浪费了。因此将 1000 0000 用来表示 -128。

这也就是 为什么有负号的 char,表示的数值范围为 -128~127的原因。

其实 -128 对应的原码为11000 0000,超过位数,需要截取,截取后为 1000 0000,截取后即为 -0的原码。

如果要计算 -128 + 1 用反码计算如下

  1111 1111
  0000 0001
+ ------------ 
1 0000 0000

反码 1 0000 0000 截取后为 0000 0000。反码转原码为 1111 1111,对应的十进制为-127,符合结果预期

你可能感兴趣的:(c语言)