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

同カテゴリーの次の記事

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

この記事は、インテル® デベロッパー・ゾーンに公開されている「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 を使用しないようにします。仮に、その仕組みを良く理解している場合であってもです。意図せずこのエラーを引き起こしたり、同僚がコードを正しく理解せずに間違ってコードを変更する可能性があるからです。くどいようですが、良いプログラマーとは、さまざまな言語のトリックを使いこなすことができる人ではなく、明確で分かりやすく、初心者でも理解できるコードを記述できる人です。

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

関連記事

  • Parallel Universe マガジンParallel Universe マガジン Parallel Universe へようこそ。 米国インテル社が四半期に一度オンラインで公開しているオンラインマガジンです。インテルの技術者によるテクノロジーの解説や、最新ツールの紹介など、並列化に関する記事を毎号掲載しています。第1号からのバックナンバーを PDF 形式で用意しました、ぜひご覧ください。 12 […]
  • 比較関数の罠比較関数の罠 この記事は、インテル® デベロッパー・ゾーンに公開されている「The Evil within the Comparison Functions」の日本語参考訳です。 この記事の PDF […]
  • ファクトシート: oneAPIファクトシート: oneAPI この記事は、インテル ニュースルームに公開されている「Fact Sheet: oneAPI」の日本語参考訳です。 この記事の PDF 版はこちらからご利用になれます。 oneAPI とは? oneAPI […]
  • 並列プログラミングにおけるロックの効率的な使用並列プログラミングにおけるロックの効率的な使用 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Using Locks Effectively in Parallel Programming […]
  • インテル® IPP サンプル – エラーの修正インテル® IPP サンプル – エラーの修正 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Intel IPP Samples for Windows - error correction」の日本語参考訳です。 この記事は、PVS-Studio を使用することでプログラムがどのように安全になるかを説明した記事の 1 […]