• ベストアンサー

VC2005においてif文が正しく評価されない

環境: WindowsXP SP2 VC2005 下記ソースをデバッグしています(F10によるステップ実行)。 if文の直前で変数aの値を-1など、0未満へ変更し、 そのままステップ実行しても、なぜかif文の中に入りません。 本来であれば、-1は0未満であるため、if文の判定は真と判定 されるべきであると思います。 個人的に「a = b - c」の式が悪さをしているのではないかなと 考えています。 なぜこのような現象が起こるのでしょうか? int main(void) { long a = 0; long b = 2; long c = 1; a = b - c; if( a < 0 ){ return 0; } }

質問者が選んだベストアンサー

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.13

>> AsanoNagiさん 補足ありがとうございます。 >a = a があると、これが、「直前の式」なので、 >この結果をもとに、 if () の判定を指定 VC2005でこれを確認してみました。 XP HE VC2005 ビルドしたコード int main(void) { long a = 0; long b = 2; long c = 1; long* d = &a; a = b - c; a=a; if( a < 0 ){ return 0; }else{ return 1; } } 上記のコードで出力されたアセンブラコード ; Line 9 cmp DWORD PTR _a$[ebp], 0 jge SHORT $LN2@main となり動作が変わるようです。 結局のところ、コードを変更せずにIF文を成立させた 動作にするには直前の計算式「a = b - c;」でbかcを変更して 減算結果を負の数にしなければならないようです。

y3k
質問者

お礼

お返事が遅くなりまして申し訳ありません。解決です。 皆さんのご回答については全て拝見しておりますが、 こちらへまとめてお礼をいたしたいと思います。 最初は皆さんの環境においては再現されなかったため、 戸惑っておりましたが、正直ホッとしております。 直前の式の評価、またVCのバージョンによって、 動作が異なるということで一つ勉強になりました。 知識不足のためアセンブルについては、再度自身の 環境と照らし合わせて行こうと考えております。 これにて終了とさせていただきます。 皆さんありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (12)

回答No.2

Visual C++ は見たことがないので何ともいえませんが……。 普通、ステップ実行をしたとき、反転表示などされた行は、これから実行される行で、実行された行ではありません。 ということで、推測ですが、 a = b - c; が、反転表示(など)された時点で、 a = -1 と設定しているということはないでしょうか? ここで、ステップ実行をすると、この後で、 a = b -c が実行されてしまいます。 ですから、if() の(実行の)直前は、if() の行が反転表示(など)されたときになります。 ここで、 a = -1 と設定すれば、お考えの結果になるかもしれません。 もう一つ考えられるのは、「最適化」というものの存在です。 最近のコンパイラは、それなりに賢いので、このコードをコンパイルするときに、 ・ a, b, c を計算して if () で処理しているだけ。 ・ a, b, c は計算されているけど、その結果は使われない という判断で、 int main() { return 0: } というプログラムとしてコンパイルしてしまっている可能性もあります。

y3k
質問者

お礼

ご回答ありがとうございます。 ステップ実行の際ですが、「a = b - c」の式が実行され、 変数aの値が0から2-1すなわち1となることを確認したうえで 変数aの値を-1へ変更しています。 また、2点目の最適化についてですが、 極端な話、コード自体を数百行のプログラムの中へ 放り込んだ場合でも同様の現象が起こっていますので、 最適化の可能性は低いような気がします。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

if文の中に入っても入らなくても結果が同じだからでは?

y3k
質問者

お礼

早速のご回答ありがとうございます。 ご指摘を受けて、if文を以下のように変更してみましたが、 結果としては、変わりませんでした。 また、補足として、VC6.0では本現象は起こりませんでした。 int main(void) { long a = 0; long b = 2; long c = 1; a = b - c; if( a < 0 ){ return 1; } else{ return 2; } return 0; }

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • vc++ scanfの使い方

    vc++についてです。 最近vc++について学び始めているのですが使い方がさっぱりわかりません。 C言語は学校の方で習っておりある程度は書けるのですが・・・。 エラーは下記の通りです。 scanfを使って足し算の簡単なプログラムを作ったのですが、 デバッグ無しで実行を押すとデバッグエラーと出てしまいます。 エラー文は画像の通りです。 プログラムは、 #include<stdio.h> int main(){ int a; int b = 2; scanf("%d", a); a += b; printf("%d \n", a); return 0; } です。 テスト感覚で作ったのですが思うようにいかずどうしようかと困っています。 vc++自体が初めてなのでできれば詳しい説明お願いいたします。

  • 関数におけるif文とreturn文について

    ◎1-------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0) return; printf("%f の平方根=%f\n",n,sqrt(n)); } ----------------------------------------------- ◎2------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0){ return; printf("%f の平方根=%f\n",n,sqrt(n)); } } ----------------------------------------------- ◎3-------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0){ return; } else{ printf("%f の平方根=%f\n",n,sqrt(n)); } } -------------------------------------------------- ◎1は参考書を参考に作ったものです。 ◎1は正常に動きます。 以上3つのプログラムで、疑問に思ったのは、関数「void disp_sqrt(double n);」についてなのですが、自分はif文が文が1つでもカッコ{ }を付けたい考えなので、◎1の「void disp_sqrt(double n)」の関数のif文に{}を付けようと思い、まず◎2のように変えたところ、平方根の表示が何も出ませんでした。 return文も文の1つだと考え、◎3のような形は正常に動きました。 return文とprintf文の2つの文があるという考えは間違っているのでしょうか? 後、◎1は何故{ }が無くてもよく、◎2は何も表示されないのでしょうか? 教えていただけると嬉しいです。

  • if文の使い方について

    if文でaの値とbの値とcの値が一緒なら次の処理を行うものを作成したいのですが。 if($a==$b==$c){ 行いたい処理 }else{ その他の処理 } と書いたのですが、ダメで if($a=$b=$c){ 行いたい処理 }else{ その他の処理 } と書いたのですが、これもダメでした。 if($a==$b) {  if($b==$c)  {    処理   }else{     その他の処理   } }else{ その他の処理 } と書かいたら実行されたのですが、このように分けて書かないとダメなのですか? いいやり方がありましたら教えてください

    • ベストアンサー
    • PHP
  • If文を2つ並べると2つ目の文が実行されない。

    プログラムの中で*A*のIf文は実行されますが、*B*のIf文は実行されません。 何故でしょうか?教えて下さい。 ちなみに、<中略>の部分にもIf文は同じ様にあります。(内容は違うけど) <SCRIPT language="javascript"><!-- function ka() { ******<中略>****** *A* if (document.fomu.email.value ==""){        alert ("メールアドレスを記入して下さい。");        fomu.email.focus();        return false; } *B* if (document.fomu.email.value.match(/\w+@\w+/){        alert ("正しくメールアドレスを記入して下さい。");        fomu.email.focus();        return false; } ******<中略>******* } //--></SCRIPT>

  • IF文

    (A)IF 条件 THEN 単純実行文1 ELSE 単純実行文2 (B)IF 条件 THEN 実行処理1 ELSE 実行処理2 Aの文では単純実行分なのになぜ改行すると(B)の文みたいに実行処理になるのでしょうか? 実行処理と単純実行文の違いを教えてください

  • C言語 if文

    C言語のif文についての質問なのですが、ifを使い、条件Aの時は1のプログラムを実行、条件Bの時は2のプログラムを実行するようにしたとき、1と2のプログラム自体にもif文が使われています。その場合は、AとBの時のifと1と2に使われているifをどのように区別するのですか?(ちなみに1と2のif文については、それぞれ実行してみたところ動作可能でした。)説明が下手ですいません。初心者ですので、分かりやすく教えていただけると有難いです。

  • C言語におけるif文の評価順

    たとえば以下のようなif文で、A B C が評価される順番は 言語の規約上、明確になっているのでしょうか? if ( A && B && C ) { } また例えば A, B, C の順番に評価されるとして、B が FALSE の場合は C を評価する必要はありませんが、 この場合、Cは評価されないことは言語規約上、明確に なっているのでしょうか? 手元のコンパイラで試した結果では 評価順は A -> B -> C で B で FALSE を返すようにしたら C は実行されませんでした。 ただ、これが実装依存か、言語の標準仕様かという点が 気になっています。

  • 【ExcelVBA】IF条件を満たしているのに、IF条件のところで止まってしまう

    Sub test1() 変数1 = IsEmpty(Range("C1")) If Range("A1") > 0 And Range("B1") = 0 And 変数1 = True Then   test2 End If End Sub 止まったときのデバッグでの表示は Range("A1")は「100」(セルの中身) Range("B1")は「0」(セルの中身) 変数1はRange("C1")がエラー表示なので「True」 すべての条件を満たしているのですが、 IF条件のところで止まってしまいます。 (IF条件のところの1行が黄色くハイライトになっている状態) 止まったデバッグの後に、F5を押して実行させると、 IF条件の続きから実行されて、test2が実行されて処理が終了します。 何で、IF文のところで一度止まってしまうのかわかりません。

  • javaについて質問です

    3つの整数の中央値を求めるメソッドについて質問です。 まずは以下の2つのコードをご覧ください --------------(1)------------------ static int med3(int a,int b,int c){ if(a>=b){ if(b>= c) return b; else if(a<=c) return a; else return c; }else if(a>c) return a; else if(b>c) return c; else return b; } -----------(1)----------- -----------(2)----------- static int med3(int a,int b,int c){ if((b>=a&&c<=a)||(b<=a&&c>=a)) return a; else if((a>b&&c<b)||(a<b&&c>b)) return b; else return c; } -----------(2)----------- 上記の2つのメソッドは参考書の問題に載っているものです。 因みに問題文は、 「中央値を求める手続きは(2)のようにも実現できる。しかしこれは(1)に比べると、実行効率が悪い。その理由を考察せよ」 です。 この問題の解説について質問があります。 解説には、こうあります。 「最初のif文の判定   if ((b >= a && c<= a) || (b <= a && c >= a) に着目します。ここでb >= aおよびb <= aの判定を裏返した判定(実質的に同一の判定)が、続くelse以降で   else if ((a > b && c < b) || (b <= a && c > b) と行われます。つまり、最初のifが成立しなかった場合、2番目のifでも(実質的に)同じ判定を行っているため、効率が悪くなるのです。」 そこで2つ質問があるのですが、まず一つ目から。 「ここでb >= aおよびb <= aの判定を裏返した判定(実質的に同一の判定)が、続くelse以降でelse if ((a > b && c < b) || (b <= a && c > b)と行われます。」の部分の日本語は、一体どういう意味なのでしょうか? b >= a,b <= aの判定を裏返したものはb < a,b > aとなると思うのですが、しかしそれだとその後に続くelse if文の条件、(a > b && c < b) || (b <= a && c > b)と合いません。 2つ目の質問です。 なぜ、ifが成立しなかった場合、何故2番目のifでも同じ判定を行っていると言えるのでしょうか?

    • ベストアンサー
    • Java
  • if文について

    最近、C言語プログラムから、離れていて、久しぶりにここを覗いたのですが、 こんな質問を見ました。 質問 C言語初心者だが、学習用に良いサイトはないか? 最初の回答の方は、ある初心者用と思われるサイトを、紹介してらっしゃいました。 それに対して、他の回答者の方々は、そのサイトの一分を引用して、コンパイルできないし、間違っていると指摘されました。それは以下のようなものでした。 if(条件式) 文1; else 文2; その代わりに掲載されているのが次のようなものでした。 if(条件)条件が真のときに実行する1文; else 条件が偽のときに実行する1文; 私には、最初の回答がなぜ間違っているのか、何故コンパイルできないのか、判りません。何方か詳しく教えていただければ、嬉しいです。よろしくお願いします。