为什么我在写=而不是==时没有得到任何警告
Why am I getting no warning when writing = instead of ==?
由于以下无效语句,经过数小时的努力终于确定了一个错误:
...
assert( variable = -0.5 );
这显然应该是assert( variable == -0.5 );
:开发者打字错误。
我正在使用Visual Studio 2015进行编译,并真正致力于实现"0警告编译"。
这样一个糟糕而危险的语句怎么能在编译器没有报告任何警告的情况下编译呢?是否没有编译器选项可以避免这种情况?
编辑:即使bool b = ( variable = -0.5 )
也不会产生任何编译器警告
只有在使用/W4
编译级别时,才会警告条件表达式中的赋值,请参阅此部分。
因此,我使用在线MSVC编译器(我在这台电脑上没有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_0stagelib
,两行都警告:
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)
禁用此警告。
您不会收到警告,因为这是一个完全合法且已使用的表达式,例如
while( (char c = getNextChar()) ) ...
因此,有些人在与const进行比较时,倾向于将const写在lhs:上
assert( -0.5 = variable ); // this is an error
assert( -0.5 == variable ); // this is correct
请注意,当您有两个非常数要比较时,这不会按比例缩放;此外,记住这个规则是否比记住==
和=
更容易也是有争议的。
不幸的是,没有简单的方法可以通过静态时间分析来避免这种错误。考虑一下:
assert(var = possiblyUnsafeOp());
assert(var.otherOp() == something);
第一行证明UnsafeOp()可能返回一个非null,并且在编写测试时不能被称为错误。
该模式对于遍历列表直到找到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
是),所以除非您轻击两个=符号,否则它不会编译。
您没有任何警告,因为assert测试赋值,并且它有效。正如blobonat所说,一个更安全的代码是:-0.5 = variable
实际上,如果您想使用assert评估一些复杂的语句,但必须事先进行一些赋值,该怎么办?在这种情况下(现在想不出一个有效的例子,但我记得是这样使用的),你可以做:
assert(variable = -0.5, (do something with variable));
这显然不能在发布版本中使用,但对于复杂的断言会有所帮助。
- 在非constexpr函数上添加的constexpr限定符不会触发任何警告
- 为什么 gcc 和 clang 都没有发出任何警告?
- 是否有任何编译器标志可以在下面的代码中用于报告有关 UB 的警告?
- 如何在程序崩溃时关闭程序,没有任何警告屏幕等.C++窗口
- 是否有任何C++编译器可以发出悬而未决的引用警告?
- 如果变量未初始化,Visual Studio 2017 不会生成任何警告
- 如何使用GSL :: SPAN来修复任何数组以降低指示警告
- 海湾合作委员会警告"没有声明任何东西
- 为什么_Printf_format_string_宏不产生任何警告?
- GTK图像突然不会刷新任何错误或警告
- 为什么 G++ 不为不返回任何内容的模板方法生成警告?
- 是否有任何工具可以警告可能滥用删除或删除[]
- 将 NULL 作为对象返回时未收到任何警告
- 是否有任何方法可以避免警告/错误模板实例化回溯
- 为什么"constructor invocation"不触发任何编译器 (g++) 警告?
- 该函数 int f() 没有警告不返回任何值?
- 是否有任何编译器或选项来触发对无意义和有错误的switch语句的警告
- 如何在c++中从(void *)重新输入到int而不收到任何警告,当编译迂腐的标志
- Decltype (auto) foo()返回本地引用,没有任何警告
- cc1plus:无法识别的命令行选项警告任何其他警告