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

同カテゴリーの次の記事

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

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


4. ?: 演算子に注意して、括弧で囲む

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

V502 Perhaps the ‘?:’ operator works in a different way than it was expected. The ‘?:’ operator has a lower priority than the ‘-‘ operator. (V502 ‘?:’ 演算子の動作が期待とは異なる可能性があります。’?:’ 演算子よりも ‘-‘ 演算子のほうが優先されます。)

bool IsVisible(bool ancestorsVisible) const
{
  int16 showLevel = BView::Private(view).ShowLevel();
  return (showLevel - (ancestorsVisible) ? 0 : 1) <= 0;
}

説明

C/C++ 操作の優先順位 (英語) を確認してみましょう。三項演算子 ?: の優先順位は非常に低く、/、+、< などの演算子よりも下です。さらに、- 演算子よりも下です。そのため、プログラムはプログラマーが意図したようには動作しません。

プログラマーは、次の順序で操作が実行されると想定します。

(showLevel - (ancestorsVisible ? 0 : 1) ) <= 0

しかし、実際には次の順序で実行されます。

((showLevel - ancestorsVisible) ? 0 : 1) <= 0

このエラーは、非常に単純なコードでも発生します。これは、?: 演算子がいかに危険であるかを示しています。この演算子は、使用時にミスしやすいため、より複雑な条件での三項演算子は、コードにとって有害です。ミスに気付かない可能性が高いだけでなく、このような式は可読性を損ねます。

?: 演算子には十分に気を付けてください。私は、この演算子に関連した多数のエラー (英語) を目にしてきました。

正しいコード

return showLevel - (ancestorsVisible ? 0 : 1) <= 0;

推奨事項

以前の記事 (英語) で、三項演算子の問題について述べましたが、その後さらに懸念を深めるようになりました。上記の例は、簡潔な式であっても、ミスを犯しやすいことを示しています。このため、私は以前のヒントを更新することにしました。

?: 演算子を完全に否定するつもりはありません。場合によっては、有益であったり、必要になることもあるでしょう。しかし、過度に使用すべきではありません。また、使用する場合は、次のことを推奨します。

三項演算子は常に括弧で囲みます。

次の式について考えてみます。

A = B ? 10 : 20;

次のように括弧で囲みます。

A = (B ? 10 : 20);

この例では本来、括弧は不要です。

しかし、後でコードをリファクタリングして、次のように X 変数を 10 や 20 に加算する場合、コードを保護します。

A = X + (B ? 10 : 20);

括弧がないと、?: 演算子の優先順位が低いことを忘れてしまう可能性があります。

もちろん、間違って “X+” を括弧内に記述する可能性はありますが、その場合同じエラーになります。括弧は、追加的保護ですが、考慮すべきです。

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

関連記事

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