大负整数文字 [英] large negative integer literals
问题描述
在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屋!