大负整数文字 [英] large negative integer literals

查看:113
本文介绍了大负整数文字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Visual Studio 2010上,以下程序

  #include< iostream> 
using std :: cout;

int main()
{
cout< -2147483646< '\\\
';
cout<< -2147483647< '\\\
';
cout<< -2147483648< '\\\
'; // numeric_limits< int> :: min()
cout<< -2147483649< '\\\
';
cout<< -2147483650< '\\\
';
cout<< ...< '\\\
';
cout<< -4294967293< '\\\
';
cout<< -4294967294< '\\\
';
cout<< -4294967295< '\\\
'; // -numeric_limits< unsigned int> :: max()
cout<< -4294967296< '\\\
';
cout<< -4294967297< '\\\
';
}

生成以下输出

  -2147483646 
-2147483647
2147483648
2147483647
2147483646
...
3
2
1
-4294967296
-4294967297



这是标准行为还是Visual Studio错误? strong>正如几个人已经指出的,没有这样的东西作为负整数文字

解决方案

-2147483648 更多细节请参阅以下Keith Thompson的出色答案。 ,例如,不是整数字面值;它是由应用于文本 2147483648 的一元 - 运算符组成的表达式。



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



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

  int 
long int
long long int(C ++ 2011中的新增)

请注意,它在标准C ++中永远不是无符号类型 。在1998和2003版本的C标准(它们不具有 long long int )中,一个十进制整数文字太大,不适合 long int 导致未定义的行为。在C ++ 2011中,如果十进制整数文本不适合 long long int ,那么程序是不成形的。



但是gcc(至少从4.6.1版本开始,我有最新版本)没有实现C ++ 2011语义。不符合32位元长度的文字 2147483648 会被视为 unsigned long 在我的32位系统上。 (这对于C ++ 98或C ++ 2003是正常的;行为是未定义的,所以编译器可以做任何喜欢的东西。)



bit 2's-complement int type,this:

  cout< ; -2147483647< '\\\
';

使用 int 2147483647 ,将其取反,并打印结果,其与您期望的数学结果相匹配。但是:

  cout< -2147483648< '\\\
';

(使用gcc 4.6.1编译时)使用 long unsigned long value 2147483648 ,将其作为unsigned int <产生 2147483648 ,并打印出来。



像其他人提到的,可以使用后缀强制特定类型。



这是一个小程序,您可以用它来显示编译器如何处理字面量:

  #include< iostream> 
#include< climits>

const char * type_of(int){returnint; }
const char * type_of(unsigned int){returnunsigned int; }
const char * type_of(long){returnlong; }
const char * type_of(unsigned long){returnunsigned long; }
const char * type_of(long long){returnlong long; }
const char * type_of(unsigned long long){returnunsigned long long; }

int main()
{
std :: cout< int:<< INT_MIN << ..< INT_MAX<< \\\
;
std :: cout<< long:<< LONG_MIN<< ..< LONG_MAX < \\\
;
std :: cout<< long long:<< LLONG_MIN<< ..< LLONG_MAX<< \\\
;

std :: cout<< 2147483647是类型<< type_of(2147483647)<< \\\
;
std :: cout<< 2147483648是<< type_of(2147483648)<< \\\
;
std :: cout<< -2147483647是<< type_of(-2147483647)<< \\\
;
std :: cout<< -2147483648是<< type_of(-2147483648)<< \\\
;
}

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

  lits.cpp:18:5:warning:这个十进制常量仅在ISO C90中无符号
lits.cpp:20:5:warning :此十进制常数仅在ISO C90

中无符号,并且以下输出,即使 gcc -std = c ++ 0x

  int:-2147483648 .. 2147483647 
long:-2147483648 .. 2147483647
long long:-9223372036854775808 .. 9223372036854775807
2147483647是类型int
2147483648是unsigned long类型
-2147483647是类型int
-2147483648是unsigned long类型

我得到与VS2010相同的输出,最少使用默认设置。


On Visual Studio 2010 the following program

#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';
}

generates the following output

-2147483646
-2147483647
2147483648
2147483647
2147483646
...
3
2
1
-4294967296
-4294967297

What is going on?

Is this standard behavior or a Visual Studio bug?

Edit: As several people have pointed out, there is no such thing as a negative integer literal. See Keith Thompson's excellent answer below for more details.

解决方案

-2147483648, for example, is not an integer literal; it's an expression consisting of a unary - operator applied to the literal 2147483648.

Prior to the new C++ 2011 standard, C++ doesn't require the existence of any type bigger than 32 bits (C++2011 adds long long), so the literal 2147483648 is non-portable.

A decimal integer literal is of the first of the following types in which its value fits:

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

Note that it's never of an unsigned type in standard C++. In the 1998 and 2003 versions of the C standard (which don't have long long int), a decimal integer literal that's too big to fit in long int results in undefined behavior. In C++2011, if a decimal integer literal doesn't fit in long long int, then the program is "ill-formed".

But gcc (at least as of release 4.6.1, the latest one I have) doesn't implement the C++2011 semantics. The literal 2147483648, which doesn't fit in a 32-bit long, is treated as unsigned long, at least on my 32-bit system. (That's fine for C++98 or C++2003; the behavior is undefined, so the compiler can do anything it likes.)

So given a typical 32-bit 2's-complement int type, this:

cout << -2147483647 << '\n';

takes the int value 2147483647, negates it, and prints the result, which matches the mathematical result you'd expect. But this:

cout << -2147483648 << '\n';

(when compiled with gcc 4.6.1) takes the long or unsigned long value 2147483648, negates it as an unsigned int, yielding 2147483648, and prints that.

As others have mentioned, you can use suffixes to force a particular type.

Here's a small program that you can use to show how your compiler treats literals:

#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";
}

When I compile it, I get some warnings:

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

and the following output, even with 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

I get the same output with VS2010, at least with default settings.

这篇关于大负整数文字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆