• ベストアンサー

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.12

No.10 の方の回答でつじつまは合うようです。 > VC2003のアセンブリコード > ; Line 9 > jns SHORT $L475 とのことなので、直前の行の、 a = b - c; の計算結果が(通常は、これが、a に代入されるから)正か負かで判断していることになります。 ですから、この式が実行された後で、a の値を変更しても、b - c の計算結果の正負で if () の判定がなされている形になります。 No.9 の方の回答にあるように、 a = a があると、これが、「直前の式」なので、この結果をもとに、 if () の判定を指定るっぽいですね。 もしも、この仮定どおりであれば、No.9 の方のコードで、a = a を実行した後に、a の値を変更しても、無効だということになります。

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

肝心のビルドしたコード貼ってなかった; int main(void) { long a = 0; long b = 2; long c = 1; long* d = &a; a = b - c; if( a < 0 ){ return 0; }else{ return 1; } }

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

なるほど、VC2003でも同じ現象が起こりました。 VC6とアセンブリコードを比較したところ比較の場合のコードが 微妙に違っています。 VC6のアセンブリコード ; Line 9 cmp DWORD PTR _a$[ebp], 0 jge SHORT $L470 VC2003のアセンブリコード ; Line 9 jns SHORT $L475 VC6では比較時に、きちんとjge命令で大小比較を行っていますが VC2003ではjns命令で大小比較を行っているわけではないようです。 jns命令はZFフラグが在るかどうかでジャンプするかを決めるので、 今回はこれが原因ではないかと考えられます。 #アセンブリあまり詳しくないので申し訳ないですが、 #この当たりはCPUとかも絡んでくるのでしょうかね。。。;

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.9

> なお、拡張子は*.cとしています。 なるほど・・・「空のプロジェクト」に.cファイルを追加して実行してみると、動きが変ですね。 ちょと試してみましたが、 -------------------------- int main(void) { long a = 0; long b = 2; long c = 1; a = b - c; a = a; if( a < 0 ){ return 0; } } -------------------------------------- の様に、該当変数を変更するコードを追加して、 ここにブレイクポイントを設定して変数の内容を変更すると、 ちゃんと動作するようですね。 if文の評価タイミングと、ウォッチ式の変更内容の反映タイミングが変なんですかね・・・ 現象は確認できましたが・・・原因は分からないです・・・ 申し訳ないです。

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

>最適化の可能性は低いような気がします。 VCではDebug版ではデフォルトで最適化はOFFに成っているので ステップ実行してソースが見えている時点で最適化では無いと 思います。 >>No6さん 「1となることを確認したうえで」とあるので、 それは無いのでは無いでしょうか?仮に「a = b - c;」ここだと aはまだ0ですし。。。 ちなみに私も試してみましたが、わたしの環境ではif文に入りました。 「if文の中に入りません」というのをどのように確認したかに よりますが単純に戻り値を変更すればどちらを通ったかくらいは 判るとうので失礼ながら質問者さんがファンクションキー連打していて 素通りしていたとかありませんか? あと、プログラムの戻り値はどうなっていたのでしょうか? 提示されたコードにはReturnパスが無い場合がありますが、 デフォルトで私の環境では1が返却されてました0が帰っていれば if文を通ったということになると思います。 #実はaをunsignedにしていたとか言うことなら話は別なのですが:-p 確認した環境。 XP Pro Sp2 VC++6.0

y3k
質問者

お礼

> VCではDebug版ではデフォルトで最適化はOFFに成っているので > ステップ実行してソースが見えている時点で最適化では無いと > 思います。 大変申し訳ございません。無効となっておりました。 VC++6.0にて確認を行われたとのことですが、 No.1様の回答にも記載していますようにVC++6.0では 問題なくif文の中に入っています。 ファンクションキー連打等もありません。 プログラムの戻り値についてですが、下記ソースにて 確認を行いましたが、ifの中に入らずelseの中へ 入ってしまいました。結果として、返すべき値でない -1を返していました。 #include <stdio.h> short sub(void); int main(void) { signed short s = 1; s = sub(); printf( "%d", s ); return 0; } short sub(void) { signed long a = 0; signed long b = 2; signed long c = 1; a = b - c; if( a < 0 ){ return 0; } else{ return -1; } } なかなかご説明するのが難しいため、動画として 撮影できれば望ましいのですが(´・_・`)

y3k
質問者

補足

この回答へのお礼を記載した後ですが、補足いたします。 下記へ事象の経過を撮影した画像をアップいたしました。 http://www.jpdo.com/link/1/img/598.gif (1)aの値を-1へ変更し、ステップ実行 (2)当該事象が発生してます たびたび補足で申し訳ないですが、a = b - cの式を省き、 aを-1で初期化した場合は問題なく動作(ifの中へ入る)し、 逆にifを評価する直前に1を設定すると、問題なく動作 (elseの中へ入る)します。 短時間に多くの方からのご回答をいただき感謝しています。 只今から月曜までの間はVC++に触ることができませんので、 よろしくおねがいします。

回答No.7

あと考えられるのは ※ウォッチでaの値を変更した後、リターンキーを入力していない。 とかいうやつかも知れませんねぇ。 自分もよくやります(笑)。

y3k
質問者

お礼

ご回答ありがとうございます。 もしかすると!と思いましたが、きちんとEnterキーを押していました。 また、値を変更した後、ソースコード上のaへカーソルを当てた際、 aの値が-1となっていることを確認しています。

noname#140971
noname#140971
回答No.6

再回答: a = b - c; の行でストップしているのでは? ここで デバッグで a を操作しても・・・。 ちょっと試していたら、こういう操作をしてしまいました。

y3k
質問者

お礼

再度行いましたが、 if( a < 0 ){ にてストップしています。

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.5

以下の手順で試してみましたが・・・ (1)VisualStudio2005Standardを起動 (2)VisalC++の「CLRコンソールアプリケーション」を新規に作成。 (3)作成されたコード内のmainの記述を提示されたコードに変更 (4)ifの行にブレイクポイントを設定してデバッグ実行 (5)変数「a」を「ウォッチに追加」 (6)値を「1」から「-1」に変更 (7)ステップインを実行 「retuen 0」に移動しましたけど・・・

y3k
質問者

お礼

ありがとうございます。(1)~(7)の手順に基づいて行ったところ、 本来実行されるべき「return 0」の行へ移動しました。 (下記ソース参照) // aaa.cpp : メイン プロジェクト ファイルです。 #include "stdafx.h" using namespace System; int main(array<System::String ^> ^args) { char a = 0; char b = 2; char c = 1; a = b - c; if( a < 0 ){ return 0; } } 私がはじめに質問した際に記載したソースではどうなりますでしょうか? なお、拡張子は*.cとしています。 また、補足としましてデータ型がlongとintのみ本事象が確認できました。 char型とshort型の場合は問題なく動作しています。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.4

逆アセンブルしてみるのが一番手っ取り早い気がします。

y3k
質問者

お礼

ご回答ありがとうございます。逆アセンブルをしたいのはやまやまなのですが、 手順や考え方などを学ぶために膨大な時間が必要となりますので控えておきます。

noname#140971
noname#140971
回答No.3

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> <html> <title>TEST</title> <meta http-equiv="Content-script-Type" content="type"> <body> <script> var a = 0; var b = 2; var c = 1; a = b - c; document.write ((a<0), "<br/>"); </script> </body> </html> 画面には false と表示されますよ! a = c - b; document.write ((a>0), "<br/>"); なら true でしょうが・・・。

y3k
質問者

お礼

ご回答ありがとうございます。 大変申し訳ないのですが、お答えいただいた内容はJavaScriptではないでしょうか? C言語(VC2005)のみで確認している事象でして、if文の判定を行う際にデバッガによって変数aの値を-1へ変更することにより、FALSEではなくTRUEとして扱われてしまうのです。

関連するQ&A