在Visual Studio 2010上使用以下程序
#include <iostream>
using std::cout;
int main()
{
cout << -2147483646 << '\n';
cout << -2147483647 << '\n';
cout << -2147483648 << '\n'; // numeric_limits<int>::min()
cout << -2147483649 << '\n';
cout << -2147483650 << '\n';
cout << "..." << '\n';
cout << -4294967293 << '\n';
cout << -4294967294 << '\n';
cout << -4294967295 << '\n'; // -numeric_limits<unsigned int>::max()
cout << -4294967296 << '\n';
cout << -4294967297 << '\n';
}
生成以下输出
-2147483646
-2147483647
2147483648
2147483647
2147483646
...
3
2
1
-4294967296
-4294967297
发生了什么事?
这是标准行为还是Visual Studio错误?
编辑:正如有几个人所指出的,没有负整数文字这样的东西。有关详细信息,请参阅下面的Keith Thompson的优秀答案。
答案 0 :(得分:16)
-2147483648
不是整数文字;它是一个由应用于文字-
的一元2147483648
运算符组成的表达式。
在新的C ++ 2011标准之前,C ++不要求存在任何大于32位的类型(C ++ 2011添加long long
),因此文字2147483648
是不可移植的
十进制整数文字是其值适合的以下第一种类型:
int
long int
long long int (new in C++ 2011)
请注意,它从来不是标准C ++中的无符号类型 。在C标准的1998和2003版本(没有long long int
)中,一个太大而不适合long int
的十进制整数文字会导致未定义的行为。在C ++ 2011中,如果十进制整数文字不适合long long int
,则程序“格式错误”。
但是gcc(至少从版本4.6.1开始,我拥有的最新版本)没有实现C ++ 2011语义。文字2147483648
,不适合32位长,被视为unsigned long
,至少在我的32位系统上。 (这对于C ++ 98或C ++ 2003来说很好;行为是未定义的,因此编译器可以做任何喜欢的事情。)
所以给定一个典型的32位二进制补码int
类型,这个:
cout << -2147483647 << '\n';
取int
值2147483647
,否定它,并打印出与您期望的数学结果相匹配的结果。但是这个:
cout << -2147483648 << '\n';
(使用gcc 4.6.1编译时)取long
或unsigned long
值2147483648
,将其否定为unsigned int ,产生{{1打印那个。
正如其他人所提到的,您可以使用后缀来强制使用特定类型。
这是一个小程序,可用于显示编译器如何处理文字:
2147483648
当我编译它时,我收到一些警告:
#include <iostream>
#include <climits>
const char *type_of(int) { return "int"; }
const char *type_of(unsigned int) { return "unsigned int"; }
const char *type_of(long) { return "long"; }
const char *type_of(unsigned long) { return "unsigned long"; }
const char *type_of(long long) { return "long long"; }
const char *type_of(unsigned long long) { return "unsigned long long"; }
int main()
{
std::cout << "int: " << INT_MIN << " .. " << INT_MAX << "\n";
std::cout << "long: " << LONG_MIN << " .. " << LONG_MAX << "\n";
std::cout << "long long: " << LLONG_MIN << " .. " << LLONG_MAX << "\n";
std::cout << "2147483647 is of type " << type_of(2147483647) << "\n";
std::cout << "2147483648 is of type " << type_of(2147483648) << "\n";
std::cout << "-2147483647 is of type " << type_of(-2147483647) << "\n";
std::cout << "-2147483648 is of type " << type_of(-2147483648) << "\n";
}
以及以下输出,即使是lits.cpp:18:5: warning: this decimal constant is unsigned only in ISO C90
lits.cpp:20:5: warning: this decimal constant is unsigned only in ISO C90
:
gcc -std=c++0x
我使用VS2010获得相同的输出,至少使用默认设置。
答案 1 :(得分:2)
当我在GCC中编译它时,我收到以下消息:
warning: this decimal constant is unsigned only in ISO C90 [enabled by default]
在(包括)
之后的每一行都会发生cout << -2147483648 << '\n'; // numeric_limits<int>::min()
所以正在发生的事情是Visual Studio的编译器和GCC允许我们编写这些文字,他们只是将它们视为标记为无符号。这解释了打印内容的行为,这使我非常确信输出是正确的(假设我们在数字上放置了u
后缀)。
我仍然觉得有趣的是-2147483648
不是有效的有符号整数文字,即使它是有效的有符号整数值。对那个人有什么想法吗?