プログラマ ずんべ の日記

zunbe

プログラマ ずんべ の日記
プログラマ ずんべ の日記

探し物は見つかりましたか? サイト内検索を試してください。

(その1) どのファイルを処理するべきか (その1) どのファイルを処理するべきか 配列名と変数名 配列名と変数名

2005/07/15

【プログラミング】演算の優先順位と評価順序

演算には優先順位がある。
たとえば、「2-3*4」という式で、「3*4」の演算が先に行われ、次に「2-12」が計算される。
これが演算の優先順位である。

ところが、長年プログラミングをやっている人でも、評価順序があることを知らない人は多い。
評価順序とは、「3*4」という演算で、「3」が先に評価されるか、「4」が先に評価されるかという事である。
一般的に、評価は左から右に行われるので、問題になる事はまずない。
しかし、ほとんどの言語において、評価順序は処理系依存となっており、必ずしも左から右に評価されるとは限らない。

以下のコードは、よく見かけるコードだが、潜在的にバグを含んでいる。

-----
if ((p != NULL) && (p->func() == true))
{
  // 処理
}
-----

このコードは、左から右に評価される事を前提に記述されているが、先の通り、評価順序は左から右とは限らない。
つまり、「p->func() == true」が先に評価される可能性があり、変数 p が NULL の時、アプリケーションエラーを引き起こす。

「式は左から右に評価される」と明示的に仕様として確定されてもよさそうな気がするのだが。

■2006/0915追記

ななしさんより、「C/C++では、&&、|| などの演算での評価順序は、左から右と規格で決まっている」というご指摘を頂きました。
調査したところ、C/C++ではご指摘の通りであり、C/C++で記述した上記のサンプルは不適切でした。
しかしながら、他の演算子や、他の言語では、やはり、評価順序は不定であるため、プログラムの作成に際して注意を要する事は変わりありません。



このエピソードはいかがでしたか?

投稿者 zunbe : 2005/07/15 16:18:33


コメント

if ((p != NULL) && (p->func() == true))
{
  // 処理
}

こういうかき方できると、if の階層が1つ浅くなって、だいぶコードがすっきりしますよね・・・。
C のポインタじゃなくても、最近じゃクラスのインスタンスが有効かどうかってチェックが必要なんで、上(の if が2つになってるパターンの)コード、たくさん書きますよね・・・。

投稿者 GOTTi : 2005/07/16 00:19:04

まあ、一般的には、式は左から右に評価されていくと思うので、こういったコードを書いても、まず問題は起こらないと思う。

ずんべの場合、できるだけ、左にネストしないようにコードを設計することが多い。
一般的に、p==NULL の場合、その関数内の処理はできなくなってしまうことが多いので、こんな風にする事が多い。

-----
if (p == NULL)
  goto DO_ERROR;

if (p->func() != true)
  goto DO_SUCCESS;
-----

基本的に、コードを下へ下へと伸ばしていきます。
goto が良いか、悪いか、という事については、また別の講釈で。

投稿者 ずんべ : 2005/07/16 04:59:02

 このようなシンプルな場合に限ると、goto で終了処理へ飛ばすのは賛成です。

 C# なんかで書いているときは、p==NULL みたいな箇所でわざわざ別途終了処理書いて return しているコードあります。
気持ち悪いですが、わざわざ try~catch 書いて例外発生させるのも大げさ?かと考えています。

 1点、if 文では本体が1行でも必ず中括弧つけるのが僕のポリシーです。(その方がメンテナンス性が高いと僕は思っています。)
 この議論とは関係ないですが・・・。

投稿者 GOTTi : 2005/07/16 06:06:00

誰もつっこまないので今更ながら。
&&と||と,(※)の演算子は特別に左から右へと評価されることが決まっている。(※関数呼び出しの括弧の中のコンマではない)
しかも&&と||は、左側が偽(&&)または真(||)になった場合、右側の式は全く評価されないことも定められている。
つまりif ((p != NULL) && (p->func() == true))は全く問題ないのだ。
(あえて言うとしたらtrueと比較しているのが気になるが、それはまた別の話)

投稿者 ななし : 2006/09/14 15:12:37

ななしさん>
ご指摘ありがとうございます。
ご指摘の件を確認しました。

 C Sequence Points
 C++ Sequence Points

なるほど、確かに、Visuak C / Visual C++ では、&&、|| などの演算は、左側を先に評価すると書かれていますね。
ANSI の言語規格などの文献は見つけられませんでしたが、ご指摘の通りですね。
ありがとうございます。

ただし、C/C++で &&、|| などの評価順序が例外として規定されている事を私は知りませんでしたので、サンプルをCで記載しましたが、この文章は、C/C++ に特化したものではありませんので、念のため。

ご指摘ありがとうございました。m(__)m

投稿者 ずんべ : 2006/09/15 12:24:55


コメントしてください






保存しますか?


スパム対策:
この入力フィールドに「9」と入力してください。


プログラマ ずんべ の日記:ずばヒット アマゾン