一、 引言
+0的原码是00 00 00 00;反码是 00 00 00 00;补码是 00 00 00 00;
-0的原码是80 00 00 00;反码是 FF FF FF FF;补码是 00 00 00 00;
用补码表示时,+0和-0是相同的,符合正常认知。
二、 解释
2.1、 基础
由此引出计算机中补码的表示规则:正数和零暂不讨论,需要额外注意负数的转换规则。
对于负数进行探讨:
原码 -> 补码 符号位不变,按位取反后+1;
补码 -> 原码 符号位不变,-1后按位取反;
以8位二进制来表示有符号数为例,-128的补码是0x10,按照补码转换成原码的规则,没有办法保证在符号位不变的前提下,得出原码。所以我们得到一个结论:
最小负数只有补码,不存在原码和反码。
2.2、 补充
容易与单目运算符~(取反运算符)和-(求补运算符)混淆。下面再举一个例子,对于4位二进制表示的有符号数:
x = -4;(运算时都是以补码的形式参与运算)。
其原码为1100;反码为1011;补码为1100;
如果对x进行求补运算(每一位取反再+1),-x = ~x + 1;即0011+0001=0100(4)。
从上述例子我们可以看到:x的补码是1100;对x进行求补的结果是0100,这两者是不一样的。
2.3、 实例
int i=-2147483648;
(k为二进制整数可表示的状态有2^k种。负数有2^(k-1)个,正数和0共有2^(k-1)个。int类型占4个字节,负数有2^31个,最小负数就是-2^31=-2147483648。)
i 的补码为80 00 00 00;-1的补码为ff ff ff ff;
-i-1的结果是 ???(-i)+(-1) => i的求补结果和1的求补结果相加;
-i = ~i+1 => 7f ff ff ff + 00 00 00 01 = 80 00 00 00;
-1 = ~1+1 => ff ff ff fe + 00 00 00 01 = ff ff ff ff;
相加为7f ff ff ff = 2147483647。
2.4、 代码验证
#include<stdio.h>
#define INT_MIN (-2147483647 - 1)
int main()
{
int i = INT_MIN;
printf("%d", -i - 1);
return 0;
}
说明:代码中-2147483648要以宏的形式间接给出的原因参见errorC4146: 一元负运算符应用于无符号类型,结果仍为无符号类型