之前遇到了一个两个unsigned类型数据相减,结果应为一个负数,但由于返回值类型为unsigned型,却得到了一个大数的情况。这篇文章正好解决了这个问题。
先看几张图:
在计算机中,4位无符号数表示为:
有符号数原码表示为,其中,最高位为符号位,0正1负:
有符号数的反码表示为(复习一下什么是反码,原码除符号位,各位取反):
有符号数的补码表示为(复习一下,补码是反码末位加一,同时符号位参与进位操作):
可能很多人有困惑,1000在反码中表示-7,在补码中怎么就成了-8呢?暂且认为这是一种规定吧,很神奇!
那么我们先来了解一下计算机为什么要用补码?
主要出于两个考虑,一个是减法运算可变为加法运算,另一点是没有正负0这个概念。
减法运算是怎么计算的。看一个例子,如5-6=5+(-6)=-1,即0101+1010=1111,恰好为-1的补码。再看一个加法溢出的例子,如5+6=11应该是正确的,但0101+0110=1011,为-5。
在图中,加法是顺时针移动的,减法是逆时针移动的。
考虑一下补码编码的规律,从100...0-111...1是从负数的最小数(-2^n,n代表位数-1)到-1,非负数则从00...00到01...11顺次增大,最大值为2^n-1。
看一段程序的运行结果:
INT_MAX+1=01...1+00...1=10...0,为最小负数。
INT_MAX+INT_MAX=01...1+01...1=111...10为-2。
INT_MIN-1=10...0+111...1=011...1,为最大正数。
INT_MIN+INT_MIN=10..0+10...0=0000,为0。
是不是好理解多了?