C++ 有符号/无符号比较
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5416414/
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
Signed/unsigned comparisons
提问by Peter
I'm trying to understand why the following code doesn't issue a warning at the indicated place.
我试图理解为什么下面的代码没有在指定的地方发出警告。
//from limits.h
#define UINT_MAX 0xffffffff /* maximum unsigned int value */
#define INT_MAX 2147483647 /* maximum (signed) int value */
/* = 0x7fffffff */
int a = INT_MAX;
//_int64 a = INT_MAX; // makes all warnings go away
unsigned int b = UINT_MAX;
bool c = false;
if(a < b) // warning C4018: '<' : signed/unsigned mismatch
c = true;
if(a > b) // warning C4018: '<' : signed/unsigned mismatch
c = true;
if(a <= b) // warning C4018: '<' : signed/unsigned mismatch
c = true;
if(a >= b) // warning C4018: '<' : signed/unsigned mismatch
c = true;
if(a == b) // no warning <--- warning expected here
c = true;
if(((unsigned int)a) == b) // no warning (as expected)
c = true;
if(a == ((int)b)) // no warning (as expected)
c = true;
I thought it was to do with background promotion, but the last two seem to say otherwise.
我还以为是后台提升的问题,但是最后两个好像不是这样说的。
To my mind, the first ==
comparison is just as much a signed/unsigned mismatch as the others?
在我看来,第一次==
比较与其他比较一样是有符号/无符号不匹配吗?
回答by Erik
When comparing signed with unsigned, the compiler converts the signed value to unsigned. For equality, this doesn't matter, -1 == (unsigned) -1
. For other comparisons it matters, e.g. the following is true: -1 > 2U
.
比较有符号和无符号时,编译器将有符号值转换为无符号值。对于平等,这无关紧要,-1 == (unsigned) -1
。对于其他比较,它很重要,例如以下情况为真:-1 > 2U
.
EDIT: References:
编辑:参考:
5/9: (Expressions)
5/9:(表情)
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
If either operand is of type long double, the other shall be converted to long double.
Otherwise, if either operand is double, the other shall be converted to double.
Otherwise, if either operand is float, the other shall be converted to float.
Otherwise, the integral promotions (4.5) shall be performed on both operands.54)
Then, if either operand is unsigned long the other shall be converted to unsigned long.
Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.
Otherwise, if either operand is long, the other shall be converted to long.
Otherwise, if either operand is unsigned, the other shall be converted to unsigned.
许多期望算术或枚举类型的操作数的二元运算符会以类似的方式导致转换并产生结果类型。目的是产生一个通用类型,它也是结果的类型。这种模式称为通常的算术转换,其定义如下:
如果任一操作数是 long double 类型,则另一个应转换为 long double。
否则,如果任一操作数为双精度,则另一个应转换为双精度。
否则,如果任一操作数为浮点数,则另一个应转换为浮点数。
否则,应在两个操作数上执行积分提升 (4.5)。54)
然后,如果任一操作数是 unsigned long,则另一个应转换为 unsigned long。
否则,如果一个操作数是一个long int而另一个是unsigned int,那么如果一个long int可以表示一个unsigned int的所有值,那么这个unsigned int就应该被转换成一个long int;否则两个操作数都应转换为 unsigned long int。
否则,如果任一操作数为 long,则另一个应转换为 long。
否则,如果任一操作数是无符号的,则另一个应转换为无符号。
4.7/2: (Integral conversions)
4.7/2:(积分转换)
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2nwhere n is the number of bits used to represent the unsigned type). [Note: In a two's complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). ]
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模 2 n,其中 n 是用于表示无符号类型的位数)。[注意:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。]
EDIT2: MSVC warning levels
EDIT2:MSVC 警告级别
What is warned about on the different warning levels of MSVC is, of course, choices made by the developers. As I see it, their choices in relation to signed/unsigned equality vs greater/less comparisons make sense, this is entirely subjective of course:
当然,MSVC 的不同警告级别所警告的是开发人员所做的选择。在我看来,他们关于有符号/无符号相等与更大/更少比较的选择是有道理的,这当然是完全主观的:
-1 == -1
means the same as -1 == (unsigned) -1
- I find that an intuitive result.
-1 == -1
意思相同-1 == (unsigned) -1
- 我发现这是一个直观的结果。
-1 < 2
does notmean the same as -1 < (unsigned) 2
- This is less intuitive at first glance, and IMO deserves an "earlier" warning.
-1 < 2
并不意味着与-1 < (unsigned) 2
- 乍一看不太直观,IMO 应该“更早”发出警告。
回答by Nawaz
Why signed/unsigned warnings are important and programmers must pay heed to them, is demonstrated by the following example.
以下示例说明了为什么签名/未签名警告很重要并且程序员必须注意它们。
Guess the output of this code?
猜猜这段代码的输出?
#include <iostream>
int main() {
int i = -1;
unsigned int j = 1;
if ( i < j )
std::cout << " i is less than j";
else
std::cout << " i is greater than j";
return 0;
}
Output:
输出:
i is greater than j
Surprised? Online Demo : http://www.ideone.com/5iCxY
惊讶?在线演示:http: //www.ideone.com/5iCxY
Bottomline:in comparison, if one operand is unsigned
, then the other operand is implicitly converted into unsigned
ifits type is signed!
底线:相比较而言,如果一个操作数是unsigned
,那么其他操作数隐式转换unsigned
,如果它的类型是有符号!
回答by Yochai Timmer
The == operator just does a bitwise comparison (by simple division to see if it is 0).
== 运算符只是进行按位比较(通过简单的除法来查看它是否为 0)。
The smaller/bigger than comparisons rely much more on the sign of the number.
比比较更小/更大更依赖于数字的符号。
4 bit Example:
4 位示例:
1111 = 15 ? or -1 ?
1111 = 15?或 -1 ?
so if you have 1111 < 0001 ... it's ambiguous...
所以如果你有 1111 < 0001 ......这是模棱两可的......
but if you have 1111 == 1111 ... It's the same thing although you didn't mean it to be.
但是如果你有 1111 == 1111 ......虽然你不是故意的,但这是同样的事情。
回答by Hossein
In a system that represents the values using 2-complement (most modern processors) they are equal even in their binary form. This may be why compiler doesn't complain about a == b.
在使用 2 补码(大多数现代处理器)表示值的系统中,即使在二进制形式下,它们也是相等的。这可能就是编译器不抱怨a == b 的原因。
And to me it's strange compiler doesn't warn you on a == ((int)b). I think it should give you an integer truncation warning or something.
对我来说,奇怪的是编译器没有在== ((int)b)上警告你。我认为它应该给你一个整数截断警告或其他东西。
回答by Tim Rae
The line of code in question does not generate a C4018 warning because Microsoft have used a different warning number (i.e. C4389) to handle that case, and C4389 is not enabled by default (i.e. at level 3).
有问题的代码行不会生成 C4018 警告,因为 Microsoft 使用了不同的警告编号(即C4389)来处理这种情况,并且默认情况下未启用 C4389(即级别 3)。
From the Microsoft docsfor C4389:
来自C4389的Microsoft 文档:
// C4389.cpp
// compile with: /W4
#pragma warning(default: 4389)
int main()
{
int a = 9;
unsigned int b = 10;
if (a == b) // C4389
return 0;
else
return 0;
};
The other answers have explained quite well why Microsoft might have decided to make a special case out of the equality operator, but I find those answers are not super helpful without mentioning C4389 or how to enable it in Visual Studio.
其他答案很好地解释了为什么 Microsoft 可能决定从相等运算符中创建一个特例,但我发现如果不提及 C4389 或如何在 Visual Studio 中启用它,这些答案并不是很有帮助。
I should also mention that if you are going to enable C4389, you might also consider enabling C4388. Unfortunately there is no official documentation for C4388 but it seems to pop up in expressions like the following:
我还应该提到,如果您要启用 C4389,您也可以考虑启用 C4388。不幸的是,C4388 没有官方文档,但它似乎以如下表达式弹出:
int a = 9;
unsigned int b = 10;
bool equal = (a == b); // C4388