在几个小时内挣扎,最终确定由于此无效声明而导致的错误:
...
assert( variable = -0.5 );
这显然应该是assert( variable == -0.5 );
:开发者错字。
我正在使用Visual Studio 2015进行编译,并且正在努力进行“0警告编译”。
这样一个糟糕而危险的语句如何编译而编译器不会报告任何警告?我们可以启用避免这种情况的编译器选项吗?
修改:即使bool b = ( variable = -0.5 )
也不会产生任何编译器警告
答案 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));
这显然不能在发布版本中使用,但对于复杂的断言可能会有所帮助。