INT_MIN 写成 (-2147483647 - 一) 和 vs中 warning C4018: “>”: 有符号/无符号不匹配的深入剖析-工具-IT技术博客

INT_MIN 写成 (-2147483647 - 一) 和 vs中 warning C4018: “>”: 有符号/无符号不匹配的深入剖析

时间:2019-05-15 00:34:33 浏览: 字体: 放大 缩小


INT_MIN 写成 (-2147483647 - 1) 和 vs中 warning C4018: “>”: 有符号/无符号不匹配的深入剖析。

首先明确下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”也可以解释了。

标签: