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

Why didn't the compiler warn me about an empty if-statement?

我正在使用 Keil µVision v4.74 并启用了“所有警告”选项。

我写了以下有意代码:

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 and Visual C++也这样做。

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 标志时):

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;
  • 叮当 -Wempty-body;也包含在 -Wextra 中;
  • Visual C++C4390,包含在/W3

静态分析工具:

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

所示,代码绝对有效。 它被这样解释:

if(condition)
    ;  // do nothing

// unrelated block
{
    // do something
}

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

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

或安全问题、变量污染、缓冲区管理、潜在的维护问题(如错误转换)等。有大量代码问题不属于“编译器错误”类别。

一样,这种方法可能更好,因为您不必切换编译器即可使用它。尽管我个人也发现 运行 两者独立的能力的价值。