Visual C++ 2010:如果我将"const"添加到一个比较中,为什么"signed/unsigned mismatch"会消失?

gri*_*yvp 13 c++ visual-studio-2010

我有以下简单的C++代码:

#include "stdafx.h"
int main()
{
    int a = -10;
    unsigned int b = 10;
    //  Trivial error is placed here on purpose to trigger a warning.
    if( a < b ) {
        printf( "Error in line above: this will not be printed\n" );
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用Visual Studio 2010(默认C++控制台应用程序)编译,它warning C4018: '<' : signed/unsigned mismatch" on line 7 按预期方式提供(代码有逻辑错误).

但如果我unsigned int b = 10;变成const unsigned int b = 10;警告就消失了!这种行为有哪些已知原因?gcc无论如何都显示警告const.

更新

我可以从评论中看到,很多人都建议"它只是以某种方式得到优化,所以哪里不需要警告".不幸的是,警告必要的,因为我的代码示例有精心放置触发警告实际逻辑错误:该print语句将不会被称为不管-10实际上是小于10.此错误是众所周知的,并且正好引发"签名/未签名警告"以找到此类错误.

更新

我还可以从评论中看到很多人在我的代码中"找到"了签名/未签名的逻辑错误并正在解释它.哪里不需要这样做 - 这个错误纯粹是为了触发一个警告,是微不足道的(-10对此(unsigned int)-10就是这样0xFFFFFFFF-10),问题不在于它:).

Jir*_*ika 9

这是一个Visual Studio错误,但让我们从不是错误的方面开始.

当时适用的C++标准的第5节注释9 首先讨论了如果操作数具有不同的位宽,在继续执行之前如果它们相同但符号不同的情况下该怎么做:

...否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的等级,则带有符号整数类型的操作数应转换为具有无符号整数类型的操作数的类型.

这是我们了解到比较必须在无符号算术中运行的地方.我们现在需要了解这对-10的价值意味着什么.

4.6节告诉我们:

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n,其中n是用于表示无符号类型的位数).[注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断). - 结束注释] 3如果目标类型是有符号的,如果它可以用目标类型(和位字段宽度)表示,则该值不变; 否则,该值是实现定义的.

正如您所看到的,特定的相当高的值(4294967286或0xFFFFFFF6,假设unsigned int是32位数字)与10进行比较,因此标准保证printf实际上从未调用过.

现在您可以相信我在标准中没有规则要求在这种情况下进行诊断,因此编译器可以免费发布任何规则.(事实上​​,有些人写-1的目的是产生一个全1位模式.其他人int用于迭代数组,这导致在size_t和之间进行有符号/无符号比较int.丑陋,但保证编译.)

现在Visual Studio"自愿"发出一些警告.

这会导致警告已在默认设置下(级别3):

int a = -10;
unsigned int b = 10;
if( a < b ) // C4018
{
    printf( "Error in line above: this will not be printed\n" );
}
Run Code Online (Sandbox Code Playgroud)

以下内容需要/W4发出警告.请注意,警告已重新分类.它从警告C4018变为警告C4245.这显然是设计上的.打破比较的逻辑错误几乎总是比看起来与正 - 阳性比较一起使用但与正 - 负比较分解的逻辑错误.

const int a = -10;
unsigned int b = 10;
if( a < b ) // C4245
{
    printf( "Error in line above: this will not be printed\n" );
}
Run Code Online (Sandbox Code Playgroud)

但你的情况却有所不同:

int a = -10;
const unsigned int b = 10;
if( a < b ) // no warning
{
    printf( "Error in line above: this will not be printed\n" );
}
Run Code Online (Sandbox Code Playgroud)

而且没有任何警告.(好吧,-Wall如果你想确定,你应该重试.)这是一个错误.微软:

感谢您提交此反馈.这是我们应该发出C4018警告的情况.不幸的是,考虑到我们可用的资源,这个特定问题不足以在下一个版本中修复.

出于好奇,我使用Visual Studio 2012 SP1进行了检查,但缺陷仍然存在 - 没有任何警告-Wall.