为什么 MSVC 不对有符号/无符号 == 比较发出警告?
我试图理解为什么以下代码不在指定位置发出警告。
//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'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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
当比较有符号和无符号时,编译器将有符号值转换为无符号值。对于相等性来说,这并不重要,
-1 == (unsigned) -1
。对于其他比较很重要,例如以下情况是正确的:-1 > 2U。
编辑:参考文献:
5/9:(表达式)
4.7/2:(积分转换)
EDIT2:MSVC 警告级别
MSVC 的不同警告级别所警告的内容当然是开发人员所做的选择。在我看来,他们在有符号/无符号相等与更大/更少比较方面的选择是有意义的,当然这完全是主观的:
-1 == -1
意味着与- 相同1 == (unsigned) -1
- 我发现这是一个直观的结果。<代码>-1 < 2 不与
-1 意思相同(无符号)2
- 乍一看不太直观,IMO 值得“更早”警告。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
.EDIT: References:
5/9: (Expressions)
4.7/2: (Integral conversions)
EDIT2: MSVC warning levels
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:
-1 == -1
means the same as-1 == (unsigned) -1
- I find that an intuitive result.-1 < 2
does not mean the same as-1 < (unsigned) 2
- This is less intuitive at first glance, and IMO deserves an "earlier" warning.以下示例演示了为什么签名/未签名警告很重要并且程序员必须注意它们。
猜猜这段代码的输出是什么?
输出:
惊讶吗?在线演示:http://www.ideone.com/5iCxY
底线:相比之下,如果有的话操作数是
无符号
,则另一个操作数将隐式转换为无符号
如果其类型是有符号的!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?
Output:
Surprised? Online Demo : http://www.ideone.com/5iCxY
Bottomline: in comparison, if one operand is
unsigned
, then the other operand is implicitly converted intounsigned
if its type is signed!从 C++20 开始,我们有特殊的函数来正确比较有符号和无符号值
https://en.cppreference.com/w/cpp/utility/intcmp
Starting from C++20 we have special functions for correct comparing signed-unsigned values
https://en.cppreference.com/w/cpp/utility/intcmp
== 运算符只是进行按位比较(通过简单的除法来查看是否为 0)。
较小/较大的比较更多地依赖于数字的符号。
4 位示例:
1111 = 15 ?或-1?
所以如果你有 1111 < 0001 ...这是不明确的...
但如果你有 1111 == 1111 ...这是同一件事,尽管你不是故意的。
The == operator just does a bitwise comparison (by simple division to see if it is 0).
The smaller/bigger than comparisons rely much more on the sign of the number.
4 bit Example:
1111 = 15 ? or -1 ?
so if you have 1111 < 0001 ... it's ambiguous...
but if you have 1111 == 1111 ... It's the same thing although you didn't mean it to be.
在使用 2 补码(大多数现代处理器)表示值的系统中,即使采用二进制形式,它们也是相等的。这可能就是编译器不会抱怨 a == b 的原因。
对我来说,奇怪的是编译器不会在 a == ((int)b) 上警告你。我认为它应该给你一个整数截断警告或其他东西。
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.
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.
有问题的代码行不会生成 C4018 警告,因为 Microsoft 使用了不同的警告号(即 C4389) 来处理这种情况,并且默认情况下不启用 C4389(即级别 3)。
来自 C4389 的 Microsoft 文档:
其他答案已经很好地解释了为什么 Microsoft 可能决定将相等运算符作为特殊情况,但我发现如果不提及 C4389 或 < a href="https://stackoverflow.com/questions/4151908/enable-a-single-warning-in-visual-studio">如何在 Visual Studio 中启用它。
我还应该提到,如果您要启用 C4389,您也可以考虑启用 C4388。不幸的是,C4388 没有官方文档,但它似乎出现在如下表达式中:
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).
From the Microsoft docs for C4389:
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.
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: