C++ 大负整数文本

C++ 大负整数文本,c++,C++,在VisualStudio2010上,以下程序 #include <iostream> using std::cout; int main() { cout << -2147483646 << '\n'; cout << -2147483647 << '\n'; cout << -2147483648 << '\n'; // numeric_limits<int>::m

在VisualStudio2010上,以下程序

#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';
}
发生了什么事

这是标准行为还是VisualStudio错误


编辑:正如一些人指出的那样,没有负整数文字。有关更多详细信息,请参见下面Keith Thompson的优秀答案。

当我在GCC中编译此内容时,我得到以下信息:

warning: this decimal constant is unsigned only in ISO C90 [enabled by default]
它发生在(包括)之后的每一行


例如,
cout
-2147483648
不是整数文本;它是一个表达式,由一元
-
运算符组成,该运算符应用于文本
2147483648

新C++ 2011标准之前,C++不需要任何大于32位的类型(C++ 2011加上代码>长长),因此文字<代码> 2147483648 <代码>是不可移植的。 十进制整数文字属于其值适用的以下第一种类型:

int
long int
long long int (new in C++ 2011)

注意,它不是标准C++中的无符号类型。在1998年和2003年版本的C标准(没有

long-long-int
)中,一个太大而无法放入
long-int
的十进制整数文本会导致未定义的行为。在C++2011中,如果十进制整数文本不适合
long-long-int
,则程序“格式错误”

但是gcc(至少从我拥有的最新版本4.6.1开始)没有实现C++2011语义。文字
2147483648
,它不适合32位长,至少在我的32位系统上被视为
无符号长
。(对于C++98或C++2003来说,这很好;行为是未定义的,因此编译器可以做任何它喜欢的事情。)

因此,给定一个典型的32位2的补码
int
类型,这:

cout << -2147483647 << '\n';
(使用gcc 4.6.1编译时)获取
long
unsigned long
2147483648
,将其作为无符号整数求反,生成
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";
}
和以下输出,即使使用
gcc-std=c++0x

int: -2147483648 .. 2147483647
long: -2147483648 .. 2147483647
long long: -9223372036854775808 .. 9223372036854775807
2147483647 is of type int
2147483648 is of type unsigned long
-2147483647 is of type int
-2147483648 is of type unsigned long

我得到的输出与VS2010相同,至少在默认设置下是这样。

有趣的是,这里的反汇编:cout
std::cout
的流运算符可能没有像您预期的那样提升这些文本。@ScarletAmaranth我想这没问题,因为4294967293首先被读取为无符号int,然后被否定,这会产生3。不太确定though@drhirsch:他没有使用
numeric\u limits::min()
他使用的是编译器默认使用的硬编码文本。他将
numeric\u limits
作为注释编写,以明确编译器使用的内容,他的值是正确的
-2147483648
根本不是有符号整数
2147483648
是一个整数文本(常数,真的),而
-
是一元减号运算符。可能是因为它被读取为
2147483648
,它只以无符号形式存在,然后被求反。@James:谢谢你不要这样做。我不知道,<代码> ->代码>不是C++编译时的“-STD= C++ 11”或“-STD= GNU+11”的文字的一部分,在编译时命令行中的C代码中的“-STD= C99”。这应该有帮助(它确实有助于C,但是我的C++编译器太老了,无法验证)。但是,正如你刚才解释的,整数文本从来都是未签名的。2147483648在这里应该有类型
long
。@Keith:你自相矛盾:“注意它从来不是无符号类型”和“接受无符号整数值2147483648”。你能澄清一下吗?@user763305:或者如果它是
int
long
unsigned long
,…,我想gcc就是这么做的。我想我应该试试VS2010。@user763305:与VS2010的输出相同。@KeithThompson:如果编译时在命令行中指定“-std=c++11”或“-std=gnu++11”会怎么样?“-std=c99”有助于使用类似的C代码。
cout << -2147483648 << '\n';
#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
int: -2147483648 .. 2147483647
long: -2147483648 .. 2147483647
long long: -9223372036854775808 .. 9223372036854775807
2147483647 is of type int
2147483648 is of type unsigned long
-2147483647 is of type int
-2147483648 is of type unsigned long