大的负整数文字

Joh*_*åde 10 c++

在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';
}
Run Code Online (Sandbox Code Playgroud)

生成以下输出

-2147483646
-2147483647
2147483648
2147483647
2147483646
...
3
2
1
-4294967296
-4294967297
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事?

这是标准行为还是Visual Studio错误?

编辑:有几个人指出,没有负整数文字这样的东西.有关详细信息,请参阅下面的Keith Thompson的优秀答案.

Kei*_*son 16

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

在新的C++ 2011标准之前,C++不需要存在任何大于32位的类型(C++ 2011添加long long),因此文字2147483648是不可移植的.

十进制整数文字是其值适合的以下第一种类型:

int
long int
long long int (new in C++ 2011)
Run Code Online (Sandbox Code Playgroud)

请注意,它从来不是标准C++中的无符号类型.在1998和2003版本的C标准(没有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';
Run Code Online (Sandbox Code Playgroud)

获取int2147483647,否定它,并打印结果,该结果与您期望的数学结果相匹配.但是这个:

cout << -2147483648 << '\n';
Run Code Online (Sandbox Code Playgroud)

(当使用gcc 4.6.1编译时)获取longunsigned long2147483648,将其否定为unsigned int,产生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";
}
Run Code Online (Sandbox Code Playgroud)

当我编译它时,我得到一些警告:

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
Run Code Online (Sandbox Code Playgroud)

和以下输出,即使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
Run Code Online (Sandbox Code Playgroud)

我使用VS2010获得相同的输出,至少使用默认设置.

  • 但是,正如您刚才所解释的,整数文字永远不会是无符号的.2147483648应该在这里输入`long long`. (2认同)