web-dev-qa-db-ja.com

コンパイラーが空のifステートメントについて警告しなかったのはなぜですか?

Keil uVision v4.74を使用していますが、[すべての警告]オプションを有効にしています。

私は次の意図的コードを書きました:

if(condition matched)
{
 //do something
}

プロジェクトを再構築したときに、エラー0、警告0を受け取りました。

しかし、私が偶然を書いたとき:

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

エラー0、警告0も受け取りました。

私は、小さな; if条件に続くものが問題の根本でした。

なぜコンパイラは警告としてそれを扱い、私に知らせなかったのですか?

25

空のステートメントisは有効なステートメントであるため、エラーではありません。ただし、それは確かに疑わしいコードであるため、コンパイラ警告の完璧な候補です。実際、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++C439/W3に含まれる

静的解析ツール:

  • cppcheck--enable=warning --inconclusive; --enable=all --inconclusiveに含まれています
52
Matteo Italia

Matteoの答えが示したように、コードは完全に有効です。このように解釈されています:

if(condition)
    ;  // do nothing

// unrelated block
{
    // do something
}

それは少し専門的ですが、空のボディを持つ条件にはいくつかの非常に素晴らしい使用があります。

Lintおよび他のそのようなコード健全性ツールは、インデントの予期しない変更について警告し、技術的にはコンパイラエラーではありませんが、スタイル上の追加エラーをキャッチします。

または、セキュリティの問題、変数の汚染、バッファ管理、不正なキャストなどの潜在的なメンテナンスの問題など。「コンパイラエラー」のカテゴリに分類されないコードの問題が非常に多くあります。

@ jpmc26が述べたように、このアプローチは、使用するためにコンパイラを切り替える必要がないため、より良いかもしれません。個人的には、2つを独立して実行できることにも価値があります。

2
davenpcj