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

Aks*_*l D 26 c if-statement compiler-warnings keil

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

我写了以下故意代码:

if(condition matched)
{
 //do something
}
Run Code Online (Sandbox Code Playgroud)

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

但是,当我不小心写道:

if(condition matched);
{
 //do something
}
Run Code Online (Sandbox Code Playgroud)

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

我几乎不可能发现;if条件下的一小部分是问题的根源.

为什么编译器不把它当作警告并通知我?

Mat*_*lia 51

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

int foo(int x) {
  if(x); {
    return 42;
  }
  return 64;
}
Run Code Online (Sandbox Code Playgroud)

 

/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); {
^
Run Code Online (Sandbox Code Playgroud)

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); {
^
Run Code Online (Sandbox Code Playgroud)

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

如果您无法切换到更有用的编译器,请考虑使用静态分析工具; 例如,在这种情况下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.
Run Code Online (Sandbox Code Playgroud)

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

回顾一下,相关的警告选项是:

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

静态分析工具:

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

  • 是的,MSVC警告:`警告C4390:';':发现空控制声明; 这是意图吗?` 它实际上是[3级警告](https://msdn.microsoft.com/en-us/library/8f1zx4y1.aspx),所以你甚至不需要/ W4.默认警告级别将捕获此警告级别. (4认同)
  • @ Vector9:快速查看armcc支持的警告列表,似乎没有任何与此问题相关的内容.但是,我看到Keil [确实支持](http://www.keil.com/arm/gnu.asp)使用`gcc`,所以你可以尝试一下(也许不是在制作中,但是从时间到是时候看一组不同的编译器诊断了.但同样,我不是Keil/armgcc专家,所以我不知道是否可以主要用作替代品,或者如果在编译器之间切换是一场噩梦. (3认同)