定义
-1 | 1 | |
原码 | 1000 0001 | 0000 0001 |
反码 | 1111 1110 | 0000 0001 |
补码 | 1111 1111 | 0000 0001 |
可以看出,正数的原码、反码、补码是一样的;负数的反码除了最高位,其余位按位取反,补码在反码基础上加1。
原码是给人看的,比较直观;反码是为补码而存在;补码是这个数真实存储在计算机的样子。
为什么计算机要搞补码呢?
例1,补码可以解决溢出的问题
如果计算机用原码存储,-1+1=1000 0010,就无法得到正确值。而用补码,就等于0000 0000,进位就不管了,因为是unsigned char只有8个位宽。再通过char去解析,就得到正确的值了。
例2,补码可以计算两数之差
如果要计算1-16,计算机里是0000 0001-0001 0000=1111 0001(借位忽略掉),注意结果1111 0001是补码,这个补码代表什么数,就要看你怎么解析了
如果解析为char,那他就是1111 0001-->1111 0000-->1000 1111-->-15,刚好1 - 16 = -15;
如果解析为unsigned char,那他就是1111 0001-->0xf1-->15*16+1=241,代表从0001 0000到1111 1111,再加1,共241。
#include <stdio.h>
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
int main() {
printf("%d\n",(uint8_t)(0x1-0x10));
return 0;
}
补码可以计算两数之差有什么好处呢,比如你有一个32位的计数器,假如这个计数器计到0xFFFF FFF0时,你要开始计时了,计数器很快就会溢出,假如溢出后变为0x0000 0005,这个时候只需要(unsigned int)(0x0000 0005-0xFFFF FFF0),就能计算出经过了多少时间。