(-2147483648> 0) 在 C++ 中返回 true?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14695118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:36:52  来源:igfitidea点击:

(-2147483648> 0) returns true in C++?

c++integer-overflow

提问by benyl

-2147483648 is the smallest integer for integer type with 32 bits, but it seems that it will overflow in the if(...)sentence:

-2147483648 是 32 位整数类型的最小整数,但在if(...)语句中似乎会溢出:

if (-2147483648 > 0)
    std::cout << "true";
else
    std::cout << "false";

This will print truein my testing. However, if we cast -2147483648 to integer, the result will be different:

这将true在我的测试中打印。但是,如果我们将 -2147483648 转换为整数,结果会有所不同:

if (int(-2147483648) > 0)
    std::cout << "true";
else
    std::cout << "false";

This will print false.

这将打印false.

I'm confused. Can anyone give an explanation on this?

我糊涂了。任何人都可以对此做出解释吗?



Update 02-05-2012:

2012 年 2 月 5 日更新:

Thanks for your comments, in my compiler, the size of int is 4 bytes. I'm using VC for some simple testing. I've changed the description in my question.

感谢您的评论,在我的编译器中,int 的大小为 4 个字节。我正在使用 VC 进行一些简单的测试。我已经更改了我的问题中的描述。

That's a lot of very good replys in this post, AndreyTgave a very detailed explanation on how the compiler will behaviour on such input, and how this minimum integer was implemented. qPCR4viron the other hand gave some related "curiosities" and how integer are represented. So impressive!

这篇文章中有很多非常好的回复,AndreyT非常详细地解释了编译器将如何处理此类输入,以及如何实现这个最小整数。另一方面,qPCR4vir给出了一些相关的“好奇心”以及整数的表示方式。太令人印象深刻了!

回答by AnT

-2147483648is not a "number". C++ language does not support negative literal values.

-2147483648不是“数字”。C++ 语言不支持负文字值。

-2147483648is actually an expression: a positive literal value 2147483648with unary -operator in front of it. Value 2147483648is apparently too large for the positive side of intrange on your platform. If type long inthad greater range on your platform, the compiler would have to automatically assume that 2147483648has long inttype. (In C++11 the compiler would also have to consider long long inttype.) This would make the compiler to evaluate -2147483648in the domain of larger type and the result would be negative, as one would expect.

-2147483648实际上是一个表达式:前面2147483648带有一元运算-符的正字面值。2147483648对于int您平台上范围的积极方面来说,价值显然太大了。如果类型long int在您的平台上具有更大的范围,则编译器必须自动假定它2147483648具有long int类型。(在 C++11 中,编译器也必须考虑long long int类型。)这将使编译器-2147483648在更大类型的域中进行评估,结果将是负数,正如人们所期望的。

However, apparently in your case the range of long intis the same as range of int, and in general there's no integer type with greater range than inton your platform. This formally means that positive constant 2147483648overflows all available signed integer types, which in turn means that the behavior of your program is undefined. (It is a bit strange that the language specification opts for undefined behavior in such cases, instead of requiring a diagnostic message, but that's the way it is.)

但是,显然在您的情况下,范围 oflong int与范围相同int,并且通常没有整数类型的范围比int您的平台上的范围大。这正式意味着正常量2147483648溢出所有可用的有符号整数类型,这反过来意味着您的程序的行为是未定义的。(语言规范在这种情况下选择未定义的行为,而不是需要诊断消息,这有点奇怪,但事实就是这样。)

In practice, taking into account that the behavior is undefined, 2147483648might get interpreted as some implementation-dependent negative value which happens to turn positive after having unary -applied to it. Alternatively, some implementations might decide to attempt using unsigned types to represent the value (for example, in C89/90 compilers were required to use unsigned long int, but not in C99 or C++). Implementations are allowed to do anything, since the behavior is undefined anyway.

在实践中,考虑到行为是未定义的,2147483648可能会被解释为一些依赖于实现的负值,在对其-应用一元后恰好变成正值。或者,某些实现可能决定尝试使用无符号类型来表示值(例如,在 C89/90 编译器中需要使用unsigned long int,但在 C99 或 C++ 中则不需要)。实现可以做任何事情,因为无论如何行为都是未定义的。

As a side note, this is the reason why constants like INT_MINare typically defined as

作为旁注,这就是为什么像这样的常量INT_MIN通常被定义为

#define INT_MIN (-2147483647 - 1)

instead of the seemingly more straightforward

而不是看似更直接的

#define INT_MIN -2147483648

The latter would not work as intended.

后者不会按预期工作。

回答by qPCR4vir

The compiler (VC2012) promote to the "minimum" integers that can hold the values. In the first case, signed int(and long int) cannot (before the sign is applied), but unsigned intcan: 2147483648has unsigned int???? type. In the second you force intfrom the unsigned.

编译器 (VC2012) 提升为可以保存值的“最小”整数。在第一种情况下,signed int(and long int) 不能(在应用符号之前),但是unsigned int可以:2147483648hasunsigned int???? 类型。在第二个你intunsigned.

const bool i= (-2147483648 > 0) ;  //   --> true

warning C4146: unary minus operator applied to unsigned type, result still unsigned

警告 C4146:一元减运算符应用于无符号类型,结果仍然无符号

Here are related "curiosities":

以下是相关的“好奇心”:

const bool b= (-2147483647      > 0) ; //  false
const bool i= (-2147483648      > 0) ; //  true : result still unsigned
const bool c= ( INT_MIN-1       > 0) ; //  true :'-' int constant overflow
const bool f= ( 2147483647      > 0) ; //  true
const bool g= ( 2147483648      > 0) ; //  true
const bool d= ( INT_MAX+1       > 0) ; //  false:'+' int constant overflow
const bool j= ( int(-2147483648)> 0) ; //  false : 
const bool h= ( int(2147483648) > 0) ; //  false
const bool m= (-2147483648L     > 0) ; //  true 
const bool o= (-2147483648LL    > 0) ; //  false

C++11 standard:

C++11 标准

2.14.2 Integer literals [lex.icon]

2.14.2 整数文字 [lex.icon]

An integer literal is a sequence of digits that has no period or exponent part. An integer literal may have a prefix that specifies its base and a suffix that specifies its type.

整数文字是没有句点或指数部分的数字序列。一个整型文字可能有一个指定其基数的前缀和一个指定其类型的后缀。

The type of an integer literal is the first of the corresponding list in which its value can be represented.

整数文字的类型是其值可以在其中表示的相应列表中的第一个。

enter image description here

在此处输入图片说明

If an integer literal cannot be represented by any type in its list and an extended integer type (3.9.1) can represent its value, it may have that extended integer type. If all of the types in the list for the literal are signed, the extended integer type shall be signed. If all of the types in the list for the literal are unsigned, the extended integer type shall be unsigned. If the list contains both signed and unsigned types, the extended integer type may be signed or unsigned. A program is ill-formed if one of its translation units contains an integer literal that cannot be represented by any of the allowed types.

如果整数文字不能由其列表中的任何类型表示并且扩展整数类型 (3.9.1) 可以表示其值,则它可能具有该扩展整数类型。如果文字列表中的所有类型都是有符号的,则扩展整数类型应有符号。如果文字列表中的所有类型都是无符号的,则扩展整数类型应该是无符号的。如果列表同时包含有符号和无符号类型,则扩展整数类型可以是有符号或无符号的。如果程序的一个翻译单元包含不能由任何允许的类型表示的整数文字,则程序格式错误。

And these are the promotions rules for integers in the standard.

这些是标准中整数的提升规则。

4.5 Integral promotions[conv.prom]

A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_twhose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type intif intcan represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

4.5 积分促销[conv.prom]

bool, char16_t,以外的整数类型的纯右值char32_t,或其 wchar_t整数转换等级 (4.13) 小于 int 的等级,int如果int可以表示源类型的所有值,则可以转换为类型的纯右值;否则,可以将源纯右值转换为 类型的纯右值unsigned int

回答by drzymala

In Short, 2147483648overflows to -2147483648, and (-(-2147483648) > 0)is true.

简而言之,2147483648溢出到-2147483648,并且(-(-2147483648) > 0)true

Thisis how 2147483648looks like in binary.

就是2147483648二进制文件的样子。

In addition, in the case of signed binary calculations, the most significant bit ("MSB") is the sign bit. This questionmay help explain why.

此外,在有符号二进制计算的情况下,最高有效位(“MSB”)是符号位。这个问题可能有助于解释原因。

回答by Cole Johnson

Because -2147483648is actually 2147483648with negation (-) applied to it, the number isn't what you'd expect. It is actually the equivalent of this pseudocode: operator -(2147483648)

因为-2147483648实际上对它应用2147483648了否定 ( -),所以这个数字不是您所期望的。它实际上相当于这个伪代码:operator -(2147483648)

Now, assuming your compiler has sizeof(int)equal to 4and CHAR_BITis defined as 8, that would make 2147483648overflow the maximum signed value of an integer (2147483647). So what is the maximum plus one? Lets work that out with a 4 bit, 2s compliment integer.

现在,假设您的编译器sizeof(int)等于4并且CHAR_BIT定义为8,这将使2147483648整数 ( 2147483647)的最大有符号值溢出。那么最大加一是多少呢?让我们用一个 4 位、2 秒的补码整数来解决这个问题。

Wait! 8 overflows the integer! What do we do? Use its unsigned representation of 1000and interpret the bits as a signed integer. This representation leaves us with -8being applied the 2s complement negation resulting in 8, which, as we all know, is greater than 0.

等待!8 溢出整数!我们做什么?使用其无符号表示1000并将这些位解释为有符号整数。这种表示使我们-8不得不应用 2s 补码否定导致8,众所周知,它大于0

This is why <limits.h>(and <climits>) commonly define INT_MINas ((-2147483647) - 1)- so that the maximum signed integer (0x7FFFFFFF) is negated (0x80000001), then decremented (0x80000000).

这就是为什么<limits.h>(和<climits>) 通常定义INT_MIN((-2147483647) - 1)- 以便最大有符号整数 ( 0x7FFFFFFF) 取反 ( 0x80000001),然后递减 ( 0x80000000)。