为什么在写=而不是==时没有收到警告?

时间:2016-07-21 14:24:27

标签: c++ visual-c++ visual-studio-2015

在几个小时内挣扎,最终确定由于此无效声明而导致的错误:

...
assert( variable = -0.5 );

这显然应该是assert( variable == -0.5 );:开发者错字。

我正在使用Visual Studio 2015进行编译,并且正在努力进行“0警告编译”。

这样一个糟糕而危险的语句如何编译而编译器不会报告任何警告?我们可以启用避免这种情况的编译器选项吗?

修改:即使bool b = ( variable = -0.5 )也不会产生任何编译器警告

6 个答案:

答案 0 :(得分:5)

如果您使用/W4编译级别,则仅警告条件表达式中的分配,请参阅see this

所以我在这段代码上使用在线MSVC编译器测试了它(我在这台PC上没有VS 2015):

//Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x86

#include <iostream>
#include <cassert>
int main(){
    int a;
    if (a = 2){
        std::cout << "Hello, world!\n";
    }
    assert(a = 3);
}

这个命令行:source_file.cpp -o a.exe /EHsc /MD /W4 /I C:\boost_1_60_0 /link /LIBPATH:C:\boost_1_60_0\stage\lib并且两行警告:

Warning(s):
source_file.cpp(9) : warning C4706: assignment within conditional expression
source_file.cpp(12) : warning C4706: assignment within conditional expression

显然,QT标题qglobal.h会在某些配置下使用QT_WARNING_DISABLE_MSVC(4706)禁用此警告。

答案 1 :(得分:4)

您没有收到警告,因为它是一个完全合法且使用过的表达式,例如,

while( (char c = getNextChar()) ) ...

因此,有些人在与const比较时倾向于在lhs上写const:

assert( -0.5 =  variable ); // this is an error
assert( -0.5 == variable ); // this is correct

请注意,如果您要比较两个非consts,则无法扩展;此外,记住这条规则是否更容易记住===,这是有争议的。

答案 2 :(得分:0)

不幸的是,通过静态时间分析没有简单的方法可以避免这种错误。考虑一下:

assert(var = possiblyUnsafeOp());
assert(var.otherOp() == something);

第一行证明mightUnsafeOp()返回非null,在编写测试时无法调用错误。

答案 3 :(得分:0)

您没有警告,因为断言测试分配,并且它有效。 正如blobonat所说,更安全的代码是:-0.5 = variable

答案 4 :(得分:0)

该模式对于遍历列表非常有用,直到找到0,因此人们可能会故意写这个,这就是为什么不生成警告的原因。例如:

while(int a = nextElem()){
  //Do something with a
}

而不是:

int a = nextElem();
while(a){
  //Do something with a
  a = nextElem();
}

或者仅在函数返回非0时执行某些操作,这通常意味着错误

if(int res = myFunction()){
  //Do something only if non-0
}

在你的情况下,变量被赋值为-0.5,当它被转换为int时,断言期望它被钳制为0.你可以通过改变检查的位置来避免这种情况,因为-0.5 = variable不是有效(但-0.5 == variable是),所以除非你已经推出了两个=符号,否则它不会编译。

答案 5 :(得分:-2)

这种行为实际上可以派上用场,如果你想使用assert评估一些复杂的语句但你必须事先做一些分配呢?在这种情况下(现在不能想到一个有效的例子,但我记得以这种方式使用它)你可以这样做:

assert(variable = -0.5, (do something with variable));

这显然不能在发布版本中使用,但对于复杂的断言可能会有所帮助。