-2147483648是32位整数类型中最小的整数,但它似乎会在if(…)语句中溢出:
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
这将在我的测试中打印true。然而,如果我们将-2147483648转换为整数,结果将不同:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
这将输出false。
我困惑。有人能解释一下吗?
更新02-05-2012:
感谢您的评论,在我的编译器中,int的大小是4字节。我正在使用VC进行一些简单的测试。我改变了问题中的描述。
这篇文章中有很多非常好的回复,AndreyT给出了编译器如何对这样的输入进行操作的非常详细的解释,以及这个最小整数是如何实现的。另一方面,qPCR4vir给出了一些相关的“好奇心”以及整数是如何表示的。所以印象深刻!
编译器(VC2012)提升到可以保存值的“最小”整数。在第一种情况下,带符号int(和长int)不能(在应用符号之前),但无符号int可以:2147483648有unsigned int ????类型。
在第二种情况下,将unsigned类型强制为int。
const bool i= (-2147483648 > 0) ; // --> true
警告C4146:一元负号运算符应用于无符号类型,结果仍然为无符号
以下是相关的“好奇心”:
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]
…
整数字面值是一个没有句号或的数字序列
指数的部分。一个整型字面值可以有一个前缀来指定它
基和指定其类型的后缀。
…
整型字面值的类型是对应列表的第一个
它的价值可以被表示出来。
If an integer literal cannot be represented by any type in its list
and an extended integer type (3.9.1) can represent its value, it may
have that extended integer type. If all of the types in the list for
the literal are signed, the extended integer type shall be signed. If
all of the types in the list for the literal are unsigned, the
extended integer type shall be unsigned. If the list contains both
signed and unsigned types, the extended integer type may be signed or
unsigned. A program is ill-formed if one of its translation units
contains an integer literal that cannot be represented by any of the
allowed types.
这些是标准中整数的提升规则。
4.5积分促销[convc .prom]
整数类型的prvalue,不是bool、char16_t、char32_t或
Wchar_t的整数转换秩(4.13)小于
如果Int可以表示所有,Int可以转换为Int类型的prvalue
源类型的值;否则,源prvalue可以为
转换为unsigned int类型的prvalue。
-2147483648不是“数字”。c++语言不支持负字面值。
-2147483648 is actually an expression: a positive literal value 2147483648 with unary - operator in front of it. Value 2147483648 is apparently too large for the positive side of int range on your platform. If type long int had greater range on your platform, the compiler would have to automatically assume that 2147483648 has long int type. (In C++11 the compiler would also have to consider long long int type.) This would make the compiler to evaluate -2147483648 in the domain of larger type and the result would be negative, as one would expect.
However, apparently in your case the range of long int is the same as range of int, and in general there's no integer type with greater range than int on your platform. This formally means that positive constant 2147483648 overflows all available signed integer types, which in turn means that the behavior of your program is undefined. (It is a bit strange that the language specification opts for undefined behavior in such cases, instead of requiring a diagnostic message, but that's the way it is.)
在实践中,考虑到行为是未定义的,2147483648可能会被解释为某个依赖于实现的负值,在对其应用一元后恰好变成正值。或者,一些实现可能决定尝试使用无符号类型来表示值(例如,在C89/90编译器中要求使用无符号长int,但在C99或c++中不要求)。实现可以做任何事情,因为无论如何行为都是未定义的。
顺便说一句,这就是为什么像INT_MIN这样的常量通常定义为
#define INT_MIN (-2147483647 - 1)
而不是看起来更直接
#define INT_MIN -2147483648
后者不会像预期的那样起作用。
编译器(VC2012)提升到可以保存值的“最小”整数。在第一种情况下,带符号int(和长int)不能(在应用符号之前),但无符号int可以:2147483648有unsigned int ????类型。
在第二种情况下,将unsigned类型强制为int。
const bool i= (-2147483648 > 0) ; // --> true
警告C4146:一元负号运算符应用于无符号类型,结果仍然为无符号
以下是相关的“好奇心”:
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]
…
整数字面值是一个没有句号或的数字序列
指数的部分。一个整型字面值可以有一个前缀来指定它
基和指定其类型的后缀。
…
整型字面值的类型是对应列表的第一个
它的价值可以被表示出来。
If an integer literal cannot be represented by any type in its list
and an extended integer type (3.9.1) can represent its value, it may
have that extended integer type. If all of the types in the list for
the literal are signed, the extended integer type shall be signed. If
all of the types in the list for the literal are unsigned, the
extended integer type shall be unsigned. If the list contains both
signed and unsigned types, the extended integer type may be signed or
unsigned. A program is ill-formed if one of its translation units
contains an integer literal that cannot be represented by any of the
allowed types.
这些是标准中整数的提升规则。
4.5积分促销[convc .prom]
整数类型的prvalue,不是bool、char16_t、char32_t或
Wchar_t的整数转换秩(4.13)小于
如果Int可以表示所有,Int可以转换为Int类型的prvalue
源类型的值;否则,源prvalue可以为
转换为unsigned int类型的prvalue。
因为-2147483648实际上是2147483648,对它应用了否定(-),所以这个数字不是您所期望的。它实际上相当于下面的伪代码:operator -(2147483648)
现在,假设编译器的sizeof(int)等于4,CHAR_BIT定义为8,这将使2147483648溢出整数的最大带符号值(2147483647)。所以最大值加1是多少?我们用一个4位2s补整数来算。
等等!8溢出整数!我们该怎么办?使用1000的无符号表示,并将位解释为有符号整数。这种表示留给我们的是-8应用于2s补的否定,结果是8,我们都知道,它大于0。
这就是为什么<limits.h>(和<climits>)通常将INT_MIN定义为((-2147483647)- 1)-这样最大有符号整数(0x7FFFFFFF)将被负(0x80000001),然后减去(0x80000000)。