为什么编译器没有警告我一个空的if语句?

我正在使用Keil uVision v4.74并启用了“All Warnings”选项。

我写了以下故意代码:

if(condition matched) { //do something } 

当我重建我的项目时,我得到0个错误,0个警告。

但是,当我不小心写道:

 if(condition matched); { //do something } 

我也有0个错误,0个警告。

我几乎不可能发现那么小; if条件之后是问题的根源。

为什么编译器不将它视为警告并通知我?

这不是错误,因为空语句有效语句; 然而,因为它肯定是可疑的代码,它是编译器警告的完美候选者 – 实际上gcc -Wall -Wextra确实警告过:

 int foo(int x) { if(x); { return 42; } return 64; } 

 /tmp/gcc-explorer-compiler116427-37-l1vpg4/example.cpp: In function 'int foo(int)': 2 : warning: suggest braces around empty body in an 'if' statement [-Wempty-body] if(x); { ^ 

https://godbolt.org/g/RG1o7t

clang和VC ++都是这样做的。

gcc 6甚至更聪明(好吧,也许太多了),甚至将缩进作为暗示出错了:

 /tmp/gcc-explorer-compiler116427-76-1sfy0y/example.cpp: In function 'int foo(int)': 2 : warning: suggest braces around empty body in an 'if' statement [-Wempty-body] if(x); { ^ 2 : warning: this 'if' clause does not guard... [-Wmisleading-indentation] if(x); { ^~ 2 : note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if' if(x); { ^ 

所以,要么你没有足够的警告,要么你的编译器不够聪明。

如果您无法切换到更有用的编译器,请考虑使用静态分析工具; 例如,在这种情况下, cppcheck发现错误(当给出--enable=all --inconclusive标志时):

 [mitalia@mitalia ~/scratch]$ cppcheck --enable=all --inconclusive emptyif.c Checking emptyif.c... [emptyif.c:2]: (warning, inconclusive) Suspicious use of ; at the end of 'if' statement. [emptyif.c:1]: (style) The function 'foo' is never used. 

附录 – 各种编译器的相关警告(随时更新)

总结一下,相关的警告选项是:

  • gcc -Wempty-body ; 包含在-Wextra ;
  • gcc > = 6.0,同样-Wmisleading-indentation可以提供帮助; 包含在-Wall ;
  • clang -Wempty-body ; 包含在-Wextra ;
  • Visual C ++ C4390 ,包含在/W3

静态分析工具:

  • cppcheck --enable=warning --inconclusive ; 包含在--enable=all --inconclusive

正如Matteo的回答所示,代码绝对有效。 它被解释为这样:

 if(condition) ; // do nothing // unrelated block { // do something } 

这有点技术性,但空体的条件确实有一些非常好的用途。

Lint和其他此类代码健全工具将警告缩进的意外更改,并捕获可能是风格的其他错误,尽管不是技术上的编译器错误。

或者安全问题,可变污点,缓冲区管理,潜在的维护问题,例如糟糕的演员表等。有很多代码问题不属于“编译器错误”类别。

正如@ jpmc26所提到的,这种方法可能更好,因为您不必切换编译器来使用它。 虽然我个人也发现了独立运行这两者的能力。