アプリ版:「スタンプのみでお礼する」機能のリリースについて

環境:
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;
}
}

A 回答 (13件中1~10件)

>> 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
cmpDWORD PTR _a$[ebp], 0
jgeSHORT $LN2@main
となり動作が変わるようです。

結局のところ、コードを変更せずにIF文を成立させた
動作にするには直前の計算式「a = b - c;」でbかcを変更して
減算結果を負の数にしなければならないようです。
    • good
    • 0
この回答へのお礼

お返事が遅くなりまして申し訳ありません。解決です。
皆さんのご回答については全て拝見しておりますが、
こちらへまとめてお礼をいたしたいと思います。

最初は皆さんの環境においては再現されなかったため、
戸惑っておりましたが、正直ホッとしております。

直前の式の評価、またVCのバージョンによって、
動作が異なるということで一つ勉強になりました。
知識不足のためアセンブルについては、再度自身の
環境と照らし合わせて行こうと考えております。

これにて終了とさせていただきます。
皆さんありがとうございました。

お礼日時:2008/01/12 09:01

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 の値を変更しても、無効だということになります。
    • good
    • 0

肝心のビルドしたコード貼ってなかった;


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;
}
}
    • good
    • 0

なるほど、VC2003でも同じ現象が起こりました。


VC6とアセンブリコードを比較したところ比較の場合のコードが
微妙に違っています。

VC6のアセンブリコード
; Line 9
cmpDWORD PTR _a$[ebp], 0
jgeSHORT $L470

VC2003のアセンブリコード
; Line 9
jnsSHORT $L475

VC6では比較時に、きちんとjge命令で大小比較を行っていますが
VC2003ではjns命令で大小比較を行っているわけではないようです。
jns命令はZFフラグが在るかどうかでジャンプするかを決めるので、
今回はこれが原因ではないかと考えられます。
#アセンブリあまり詳しくないので申し訳ないですが、
#この当たりはCPUとかも絡んでくるのでしょうかね。。。;
    • good
    • 0

> なお、拡張子は*.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文の評価タイミングと、ウォッチ式の変更内容の反映タイミングが変なんですかね・・・

現象は確認できましたが・・・原因は分からないです・・・
申し訳ないです。
    • good
    • 0

>最適化の可能性は低いような気がします。


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

この回答への補足

この回答へのお礼を記載した後ですが、補足いたします。

下記へ事象の経過を撮影した画像をアップいたしました。
http://www.jpdo.com/link/1/img/598.gif
(1)aの値を-1へ変更し、ステップ実行
(2)当該事象が発生してます

たびたび補足で申し訳ないですが、a = b - cの式を省き、
aを-1で初期化した場合は問題なく動作(ifの中へ入る)し、
逆にifを評価する直前に1を設定すると、問題なく動作
(elseの中へ入る)します。

短時間に多くの方からのご回答をいただき感謝しています。
只今から月曜までの間はVC++に触ることができませんので、
よろしくおねがいします。

補足日時:2008/01/11 18:48
    • good
    • 0
この回答へのお礼

> 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;
}
}

なかなかご説明するのが難しいため、動画として
撮影できれば望ましいのですが(´・_・`)

お礼日時:2008/01/11 18:34

あと考えられるのは


※ウォッチでaの値を変更した後、リターンキーを入力していない。
とかいうやつかも知れませんねぇ。
自分もよくやります(笑)。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/01/11 18:21

再回答:



a = b - c; の行でストップしているのでは?

ここで デバッグで a を操作しても・・・。

ちょっと試していたら、こういう操作をしてしまいました。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/01/11 18:19

以下の手順で試してみましたが・・・



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

「retuen 0」に移動しましたけど・・・
    • good
    • 0
この回答へのお礼

ありがとうございます。(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型の場合は問題なく動作しています。

お礼日時:2008/01/11 18:18

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

    • good
    • 0
この回答へのお礼

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

お礼日時:2008/01/11 18:10

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!