(-2147483648> 0)在C ++中返回true?

-2147483648是32位整数types的最小整数,但它似乎会在if(...)语句中溢出:

 if (-2147483648 > 0) std::cout << "true"; else std::cout << "false"; 

这将在我的testing中打印出来。 但是,如果我们将-2147483648转换为整数,结果将会不同:

 if (int(-2147483648) > 0) std::cout << "true"; else std::cout << "false"; 

这将打印false

我很困惑。 任何人都可以对此作出解释吗?


更新02-05-2012:

感谢您的意见,在我的编译器中,int的大小是4个字节。 我正在使用VC进行一些简单的testing。 我改变了我的问题的描述。

在这篇文章中有很多非常好的回复, AndreyT给出了关于编译器如何处理这种input的详细解释,以及这个最小整数是如何实现的。 qPCR4vir另一方面给了一些相关的“好奇心”,以及如何表示整数。 好印象深刻!

-2147483648不是“数字”。 C ++语言不支持负文字值。

-2147483648实际上是一个expression式:在它前面带有一元运算符的一个正面的字面值2147483648 。 在您的平台上,值为2147483648对于int范围的正面显然太大了。 如果long inttypes在你的平台上有更大的范围,编译器将不得不自动假定2147483648具有long inttypes。 (在C ++ 11中,编译器也必须考虑long long inttypes)。这会使编译器在更大types的域中计算-2147483648 ,结果将是负值,正如人们所期望的那样。

然而,显然在你的情况下, long int的范围和long int的范围是一样的,一般来说在你的平台上没有比int更大的整数types。 这正式意味着正常数2147483648溢出所有可用的有符号整数types,这又意味着程序的行为是未定义的。 (在这种情况下,语言规范select未定义的行为有点奇怪,而不需要诊断消息,但事实就是这样。)

在实践中,考虑到行为是不确定的, 2147483648可能会被解释为一些实现依赖的负值,在应用了一元运算后,这个负值会变为正值。 或者,某些实现可能会决定尝试使用无符号types来表示值(例如,在C89 / 90编译器中需要使用unsigned long int ,但不能在C99或C ++中使用)。 实现允许做任何事情,因为行为是不确定的。

作为一个侧面说明,这就是像INT_MIN这样的常量通常被定义为的原因

 #define INT_MIN (-2147483647 - 1) 

而不是看起来更直接

 #define INT_MIN -2147483648 

后者不会按预期工作。

编译器(VC2012)提升为可保存值的“最小”整数。 在第一种情况下,有signed int (和long int )不能(在符号应用之前),但unsigned int可以: 2147483648unsigned int ? types。 在第二个你强制int unsigned

 const bool i= (-2147483648 > 0) ; // --> true 

警告C4146:将一元减号运算符应用于无符号types ,结果仍为无符号

这里有相关的“好奇心”:

 const bool b= (-2147483647 > 0) ; // false const bool i= (-2147483648 > 0) ; // true : result still unsigned const bool c= ( INT_MIN-1 > 0) ; // true :'-' int constant overflow const bool f= ( 2147483647 > 0) ; // true const bool g= ( 2147483648 > 0) ; // true const bool d= ( INT_MAX+1 > 0) ; // false:'+' int constant overflow const bool j= ( int(-2147483648)> 0) ; // false : const bool h= ( int(2147483648) > 0) ; // false const bool m= (-2147483648L > 0) ; // true const bool o= (-2147483648LL > 0) ; // false 

C ++ 11标准 :

2.14.2整数文字[lex.icon]

整数文字是一个没有周期或指数部分的数字序列。 整数字面量可以有一个前缀,用来指定其基数和一个指定其types的后缀。

整数字面量的types是其中可以表示其值的对应列表的第一个。

在这里输入图像说明

如果整数字面值不能由列表中的任何types表示,并且扩展整数types(3.9.1)可以表示它的值,则它可能具有该扩展整数types。 如果文字列表中的所有types都有符号,则应对扩展整数types进行签名。 如果文字列表中的所有types均为无符号,则扩展整数types应为无符号。 如果列表包含有符号types和无符号types,则扩展整数types可以是有符号的或无符号的。 如果一个程序的某个翻译单元包含一个不能由任何允许的types表示的整数字面值,那么这个程序是不合格的。

这些是标准中整数的促销规则。

4.5积分促销 [conv.prom]

除了boolchar16_tchar32_twchar_t其整数转换等级(4.13)小于int的等级)的整数types的前值可以被转换为inttypes的prvalue,如果int可以表示源types的所有值; 否则,可以将源prvalue转换为unsigned inttypes的prvalue

总之, 2147483648溢出到-2147483648 ,和(-(-2147483648) > 0)true

这是2147483648在二进制文件中的样子。

另外,在有符号二进制计算的情况下,最高有效位(“MSB”)是符号位。 这个问题可能有助于解释原因。

因为-2147483648实际上是2147483648 ,否定( - )适用于它,这个数字不是你所期望的。 它实际上相当于这个伪代码: operator -(2147483648)

现在,假设你的编译器的sizeof(int)等于4CHAR_BIT被定义为8 ,这将使2147483648溢出一个整数( 2147483647 )的最大符号值。 那么最多加一个是多less? 让我们用4位,2s的恭维整数来解决这个问题。

等待! 8溢出整数! 我们做什么? 使用它的无符号表示forms1000并将这些位解释为有符号整数。 这个表示让我们用-8来应用二进制补码否定,结果是8 ,我们都知道,它大于0

这就是为什么<limits.h> (和<climits> )通常将INT_MIN定义为((-2147483647) - 1) ,以便最大有符号整数( 0x7FFFFFFF )被取反( 0x80000001 ),然后递减( 0x80000000 )。