• 締切済み

if文の中の条件式の評価順序について

if文の中に複数の条件式を&&演算子で結合した場合、評価順序のルールは環境によらず確定していると考えて良いでしょうか? 例として、下記のようなコードはあらゆる環境で安全であると保証できますか? ---------------------------------- CMyData* pData = new CMyData; // new演算子が失敗した場合は常にNULLを返すものとする。 if( pData != NULL && pData->HogeHoge() ) // pDataがNULLならpData->HogeHoge()はNULLポインタ参照例外 { // Do something } 条件式が左から右へと順に評価されたとして(これは言語仕様上間違いない)、最初にfalseと評価された時点で残りの条件式に関わらず条件式全体の評価はfalseと確定します。 自分より左側の条件式がfalseであった場合に、実行されると危険なコードを条件式として記述することに問題はないか? &&演算子だけでなく||演算子も気になります。 ||演算子の場合は、最初にtrueになった時点で条件式全体の評価はtrueと確定します。その時点で残りの条件式は評価されないことが保証されているのでしょうか? 私の環境でデバッグ版、リリース版でそれぞれ試してみましたが、この予想通りの結果になっていました。 Windows7 x64 VS2005 ただし一つだけ懸念があります。 このような条件式を手動で最適化しようとする場合、なるべく処理の軽い条件式が左に来るように並べ替えようと考えます。 同じようなことをコンパイラが勝手にやってしまわないかという点です。最適化のレベルや設定によっては、そのようなこともあり得るかどうか知りたいです。そのような場合、当然プログラマの意図とは異なる順序で評価されてしまい、上の例のような場合はランタイムエラーを引き起こします。

みんなの回答

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.5

>仕様がどのようになっているのか確認したかったのです。 ANSI CやISO Cの規格を確認しましょう。

katorea21
質問者

お礼

調べ方が足りなかったのでしょうか。そのものずばりの記述がありました。想定通りでした。 Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.

  • chachaboxx
  • ベストアンサー率23% (412/1777)
回答No.4

再回答です。余談です。(笑) 行数が無駄に多いコードは百害あって一利なしですが、あまりに処理を圧縮したコードはメンテナンス性に欠け、無用なコメントが増えるので本末転倒な気がします。綺麗なコードはポエムとはよくいったもので、ムダがなく明朗でかつ見た目もキレイなコードは得てして何故か速かったりします。行数を減らしてもRISC命令の処理クロックが減るとは限らないので、数行増えても全体の見通しをよくして、アルゴリズムにテコ入れしたくなる様なデザインにしておけばそのうち誰かがメンテしてくれる期待もありです。(笑) 具体的な回答に及ばず失礼しました。

katorea21
質問者

お礼

世の中には少しでも短くシンプルに書くことにエクスタシーを感じる人もいるようです。1つのif分に複数の条件を並べたり多重ネストしたりと、少し読んだだけでは意図が理解しがたいコードにもよく出くわします。 ただ、テストの目標が「1000行あたりX件の不具合を発見する」などとなっていることも良くあり、その数字を実現するためになるべく分母を小さくしようと努力した結果なのかも知れません。本末転倒ですが、見える化などと言って目標を数値化すると、人間はその数値にしか目が行かなくなってしまうようです。余談でした。

  • chachaboxx
  • ベストアンサー率23% (412/1777)
回答No.3

コンパイラが環境に依存するコードを吐くとは思えませんが、コンパイラが勘違いしないようなロジックにするのが良いプログラムだと思います。 偽を否定するより真を評価しなから非常口を設けるのがモヤモヤしなくていいと思います。

katorea21
質問者

お礼

確かにそうですね。このような書き方を好む人は、トリッキーな書き方に酔っている場合もありますが、一方でなるべく行数を減らしたいという理由もあるように思います。

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.2

>例として、下記のようなコードはあらゆる環境で安全であると保証できますか? CやC++の規格に準拠しているのでしたら保証できます。 >同じようなことをコンパイラが勝手にやってしまわないかという点です。 評価順番が仕様上決まってるものについてはしません。

katorea21
質問者

お礼

仕様がどのようになっているのか確認したかったのです。もし仕様で明確に決まっていなければ、今は良くても今後他の処理系に移植したりした場合に不具合を引き起こす可能性があります。

  • maiko0333
  • ベストアンサー率19% (840/4403)
回答No.1

「言語仕様なので確定的に動作する」から 使うというのは間違いではありません。 ただ、コードが読みにくくなったり、 一見してどっちだっけな?というような コードは書くべきではないと考えます。 言語によって似てるものが違う動きをするようなコードは 特に書くべきではないですね。

katorea21
質問者

お礼

確かにそうですね。普段あまりこのような書き方はしませんが、既にあるコードでこのような書き方をよくしているので気になったのです。

関連するQ&A

  • ifの条件式 !について

    以下処理があります。 1.宣言、初期化 var A = new Array(); A[1] = A[2] = A[3] = false; 2.条件判断 if(!A[1] && !A[2] && !A[3]){ A[1] = $A[2] = A[3] = true; }else{ 処理 } } 質問:宣言⇒ifに処理が流れた時、条件式の内容は ・A[1]の否定⇒A1は、falseが格納されているので、否定でtrue。 ・A[2]の否定⇒A1は、falseが格納されているので、否定でtrue。 ・A[3]の否定⇒A1は、falseが格納されているので、否定でtrue。 よって、 if(true && true && true){ A[1] = $A[2] = A[3] = true; } で結果、配列の1~3は、全てfalseから、trueに変更されるという考えで間違っていないでしょうか? よろしくお願いします。

  • 3っの条件式の書き方をお聞きします。

    複数条件の式の書き方をお聞きします。 A.B.C の3っの条件式です。 Aが空白のときtrue、falseを○、 Bが空白のときtrue、falseを△、 Cが空白のときtrue、falseをとします。 A B C D E F G 1○△=false:false:false=◇ 2○△=false:false:false=◇ 3○△=false:false:false=◇、 trueを1、falseを0とし、 これを DEF G 111:空白"" 110: 101:△ 011:○ 100:И 010:Е 001:Ш 000:◇ と表示したときの、 この場合のG 1.2.3の式を教えていただきたい。 式が長すぎてどうすれば良いのか分かりません。 A.B.C3っの条件式は、どう書くのでしょうか。 エ2010。

  • if文の中で否定演算子を使うことについて

    PHPの勉強をしています。 今、基礎的な内容の本とより実践的な内容の本、コードサンプルが満載の本の 計3冊で勉強しておるのですが、 たまたまなのかわかりませんが、この三冊の中ででてくるコードを見てみると、 if文の中に否定演算子、例えば IF(!A || !B) {   A、もしくはBがfalse だったのが反転してTrueになった場合の処理 }else {   A、Bどちらともtrueだったのが反転してfalseになった場合の処理 } といった条件文に否定演算子を含めたコードサンプルがほとんどです。 。。。。三冊ともこの調子なので もしかしてPHPのコーティング作法なのかな?と思いましたが ネットで検索してもそれらしい情報は見当たらず...... 自分が何がわからないのか それ自体よくわかってないのかもしれませんが IF文を使う際、条件に否定演算子を使うべきときってのがあるんだと思います。 となると、その時を判断する基準などがあるのでしょうか? 初心者なのでなにか重大な思い違いをしてるのではないかと思ってます。 なにか気づくことがあれば教えてください。

    • ベストアンサー
    • PHP
  • C言語での式の評価順序について

    ANSI C規格では 「式の評価順序は処理系により異なる」 とのことですが,次のプログラムがどのような評価順序で処理されたのか,どうしても分かりません. C言語の細かいところまでご存知の方がいらっしゃいましたら教えてください. #include <stdio.h> main(){ int c; c = 0; printf("%d\n", c + 1 == ++c); c = 0; printf("%d\n", c + 0 == ++c); } 私の処理系のccでコンパイルして実行すると 1 1 と出力されます. 上の二つの条件式が両方とも真であると解釈され得るような評価順序が存在するのでしょうか?

  • if文条件式で配列を使用したい

    if文条件式で配列を使用したい 例えば open (FH, "<data.dat"); @list = <FH>; で不確定要素数を@listに格納したあと if文でその@list内でマッチングする物があればそれだけ表示させたいのですが #ここでは比較対象をabcとして foreach(@list){ if( abc eq @list){ } } としてもtrue処理が出来ません。 どの用に条件を書けばよいのでしょうか?

    • ベストアンサー
    • Perl
  • if文が入れ子の場合の条件の解釈

    以下のようにif文が入れ子の場合についての質問です。 if(条件1){ if(条件2){ 実行内容1 } }else{ 実行内容2 } このような場合、条件1がTrueでも条件2がFalseであれば、実行内容2が実行されるのでしょうか?それともこのような場合、両方の実行内容(実行内容1及び2)が実行されないのでしょうか? もしも、上記で実行内容2が実行されない場合: やはり、条件1がTrueで、かつ、条件2=Trueの場合以外は全て実行内容2が実行されるようにするには、下記のように「and」で条件を繋ぐしかないのでしょうか? if(条件1 and 条件2){ 実行内容1 }else{ 実行内容2 } 「and」で条件を繋ぐ場合、各条件が長いとコードが見にくくて大変不便です。 何か良い方法をお知りでしたら、お教え下さい。記述方法が記載されているサイトのURL等でも結構です。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • while文の条件式に数字だけの場合の動作について

    下記コードはwhileの条件式に数字だけを入れた場合に trueかfalseを判断されるかを試したものです。 実行して見ると、10~0しか表示されず、-1以下は中断されました。 数字だけを入れた場合、0以上はtrueになり、 0よりも下はfalseと判断されるのでしょうか。 <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title></title> </head> <body> <script type="text/javascript"> var i = 10;  while( i-- ) alert(i); </script> </body> </html>

  • if else文のフローチャート

    c言語です。 if else文のフローチャートを教えてほしいです。 Trueの場合は処理1、Falseの場合は処理2を実行したいです。 最初に条件と書きます。

  • REPLACEクエリで条件文を使用するには?

    REPLACEクエリで条件文を使用するには? 以下で、bannedカラムがtrueの時だけfalseに変更しないようにするにはどうすればいいでしょうか? /*テーブルを作成*/ CREATE TABLE test (name CHAR(100) UNIQUE, banned BOOLEAN DEFAULT FALSE NOT NULL); /*bannedカラムにfalseを注入*/ REPLACE INTO test (name) VALUES('鈴木'); /*bannedカラムをfalseからtrueに変更*/ REPLACE INTO test (name,banned) VALUES('鈴木',true); /*このクエリを実行してもbannedカラムをtrueからfalseにしないようにするには*/ REPLACE INTO test (name) VALUES('鈴木');

    • ベストアンサー
    • MySQL
  • for文の条件式について

    #include<stdio.h> #define N 30 #define TRUE 1 #define FALSE 0 char is_prime[N+1]; int main(void) { for(i=1;i<=N;i++){ is_prime[i]=TRUE; } is_prime[1]=FALSE for(i=2;i*i<=N;i++)→(1) if(is_prime[i]) for(j=i*2;j<=N;j+=i)→(2) is_prime[j]=FALSE;→(3) printf("%dまでの素数は、\n",N); for(i=1;i<=N;i++) if(is_prime[i]) printf("%d",i); return 0; これはエラトステネスの素数を求めるプログラムですが、(1)のi*iは2 3 5と理解できるんですが(2)の条件式が理解できません。 例えはi=2のときjは4になるのですが、(3)は is_prime[4]=FALSEとなりj+=iは6になりますが、何ゆえこれが増分として出てくるのか理解できません。 j+=iはどういう使われ方をするのか理解できません。どなたかご教授ねがいます。