プログラミング、リファクタリング、そしてすべてにおける究極の疑問: No. 37

その他インテル® DPC++/C++ コンパイラー特集

この記事は、インテル® デベロッパー・ゾーンに公開されている「The Ultimate Question of Programming, Refactoring, and Everything」の日本語参考訳です。


37. do {…} while (…) 内の ‘continue’ 演算子に注意する

Haiku* プロジェクト (BeOS* の後継) から抜粋した以下のコードについて考えてみます。このコードにはエラーが含まれています。PVS-Studio アナライザーは、次の診断を出力します。

V696 The ‘continue’ operator will terminate ‘do { … } while (FALSE)’ loop because the condition is always false. (V696 ‘continue’ 演算子は、条件が常に false のため ‘do { … } while (FALSE)’ を終了します。)

do {
  ....
  if (appType.InitCheck() == B_OK
    && appType.GetAppHint(&hintRef) == B_OK
    && appRef == hintRef)
  {
    appType.SetAppHint(NULL);
    // try again
    continue;
  }
  ....
} while (false);

説明

do-while ループ内の continue の動作は、一部のプログラマーが想定するものと異なります。continue に到達すると、常にループ終了条件がチェックされます。これについて、詳しく説明します。プログラマーが次のようなコードを記述したとします。

for (int i = 0; i < n; i++)
{
  if (blabla(i))
    continue;
  foo();
}

あるいは、次のようなコードをを記述したとします。

while (i < n)
{
  if (blabla(i++))
    continue;
  foo();
}

ほとんどのプログラマーは直観的に、continue に到達したら制御条件 (i < n) が評価 (または再評価) され、結果が ture の場合のみ次のループ反復が開始されると理解します。しかし、次のようなコードではどうでしょうか。

do
{
  if (blabla(i++))
    continue;
  foo();
} while (i < n);

この場合、continue の前に条件がないため、多くのプログラマーは直観的に、continue の直後に次のループ反復が開始されるかのように勘違いします。しかし、continue は通常どおりに動作し、制御条件が再評価されます。

この continue の理解の欠如がエラーにつながるかどうかは、運任せです。ただし、ループ条件が常に false の場合、上記のコード例のようにプログラマーが後続の反復で処理を行う予定だと、確実にエラーになります。上記のコード例では、コード中のコメント “// try again” から、プログラマーにその意図があることが分かります。もちろん、条件が常に false になるため、”again” はあり得ません。continue に到達するとループは終了します。

つまり、この do {…} while (false) 構造では、continuebreak と同等です。

正しいコード

正しいコードの記述方法は多数あります。例えば、無限ループを作成して、continue でループの実行を継続し、break で終了します。

for (;;) {
  ....
  if (appType.InitCheck() == B_OK
    && appType.GetAppHint(&hintRef) == B_OK
    && appRef == hintRef)
  {
    appType.SetAppHint(NULL);
    // try again
    continue;
  }
  ....
  break;
};

推奨事項

do { … } while (…) 内では continue を使用しないようにします。仮に、その仕組みを良く理解している場合であってもです。意図せずこのエラーを引き起こしたり、同僚がコードを正しく理解せずに間違ってコードを変更する可能性があるからです。くどいようですが、良いプログラマーとは、さまざまな言語のトリックを使いこなすことができる人ではなく、明確で分かりやすく、初心者でも理解できるコードを記述できる人です。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

タイトルとURLをコピーしました