首先明确下4个字节的INT能表示的数字范围是2147483647—— -2147483648,来看我遇到的问题:
这里输出了“相等”说明
(INT_MIN==-2147483648)
为true。
输出了“ 1<-2147483648”,说明认为
(1<-2147483648)
为true,但是这不科学。
输出了“-1>2147483648”说明
( -1>2147483648)
为true,这也不科学。
INT_MIN和-2147483648相等,上面这些输出到底是怎么回事?来看一下INT_MIN是怎么定义的,在limits.h中
#define INT_MIN (-2147483647 - 1)
从这里我们就可以看出一些端倪,为什么不是直接写成-2147483648而是写成 -2147483647 - 1呢?原来C++标准中 -2147483648并不是一个整型的常量。在C++中一个整型常量一开始只是一个数字,没有小数点或者指数,它可能会包含一个表示进制的前缀或一个表示类型的后缀。原文如下:
“An integer constant begins with a digit, but has no period or exponent part.
It may have a prefix that specifies its base and a suffix that specifies its type.”
这里面没有提到符号,所以-2147483648实际上是一个常量表达式。由一个’-‘号和整型常量2147483648组成的常量表达式。由于我使用vs2012还停留在C89标准,C89按如下顺序匹配整形常量。
C89 : int, long int, unsigned long int
int, long int在32位机器上都是4个字节,32位的。2147483648超出了32位有符号整数的表示范围所以2147483648被认为是一个unsigned long int,然后再做’-‘操作。在vs 2012编译器中写入下图中的程序,编译时-2147483648这个常量表达式会有如下warning:
warning C4146: 一元负运算符应用于无符号类型,结果仍为无符号类型
说明-2147483648运算过中确实被转换成了无符号数2147483648,而且一元负运算符应用于无符号类型,结果仍为无符号类型。所以只要碰到-2147483648这个常量表达式,结果就是2147483648。
现在我们明白了-2147483648这个运算过程,再来分析第一张图中出现这样的问题的原因。首先来看为什么(INT_MIN==-2147483648)为true,在计算机中数字都是补码表示,
INT_MIN 补码:10000000 00000000 00000000 00000000
2147483648 补码:10000000 00000000 00000000 00000000
这两个数字的补码是相同的,所以他们当然相等。但是他们类型的不同导致了他们值的不同。输出了“ 1<-2147483648”那么就可以理解了这个表达式实际是“ 1<2147483648”当然为true。再来看最后一个输出( -1>2147483648)是怎么回事。来看vs2012在(a>b)中的如下warning,
warning C4018: “>”: 有符号/无符号不匹配
这个警告是因为a是int类型,b是unsigned类型,有符号无符号不匹配的问题,这时候编译器把a变成了无符号类型,再来看两个数的补码
a 补码:11111111 11111111 11111111 11111111
b 补码:10000000 00000000 00000000 00000000
所以这里a>b为true。那么输出的”-1>2147483648”也可以解释了。