環境:
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;
}
}
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
cmpDWORD PTR _a$[ebp], 0
jgeSHORT $LN2@main
となり動作が変わるようです。
結局のところ、コードを変更せずにIF文を成立させた
動作にするには直前の計算式「a = b - c;」でbかcを変更して
減算結果を負の数にしなければならないようです。
お返事が遅くなりまして申し訳ありません。解決です。
皆さんのご回答については全て拝見しておりますが、
こちらへまとめてお礼をいたしたいと思います。
最初は皆さんの環境においては再現されなかったため、
戸惑っておりましたが、正直ホッとしております。
直前の式の評価、またVCのバージョンによって、
動作が異なるということで一つ勉強になりました。
知識不足のためアセンブルについては、再度自身の
環境と照らし合わせて行こうと考えております。
これにて終了とさせていただきます。
皆さんありがとうございました。
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 の値を変更しても、無効だということになります。
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;
}
}
No.10
- 回答日時:
なるほど、VC2003でも同じ現象が起こりました。
VC6とアセンブリコードを比較したところ比較の場合のコードが
微妙に違っています。
VC6のアセンブリコード
; Line 9
cmpDWORD PTR _a$[ebp], 0
jgeSHORT $L470
VC2003のアセンブリコード
; Line 9
jnsSHORT $L475
VC6では比較時に、きちんとjge命令で大小比較を行っていますが
VC2003ではjns命令で大小比較を行っているわけではないようです。
jns命令はZFフラグが在るかどうかでジャンプするかを決めるので、
今回はこれが原因ではないかと考えられます。
#アセンブリあまり詳しくないので申し訳ないですが、
#この当たりはCPUとかも絡んでくるのでしょうかね。。。;
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文の評価タイミングと、ウォッチ式の変更内容の反映タイミングが変なんですかね・・・
現象は確認できましたが・・・原因は分からないです・・・
申し訳ないです。
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
この回答への補足
この回答へのお礼を記載した後ですが、補足いたします。
下記へ事象の経過を撮影した画像をアップいたしました。
http://www.jpdo.com/link/1/img/598.gif
(1)aの値を-1へ変更し、ステップ実行
(2)当該事象が発生してます
たびたび補足で申し訳ないですが、a = b - cの式を省き、
aを-1で初期化した場合は問題なく動作(ifの中へ入る)し、
逆にifを評価する直前に1を設定すると、問題なく動作
(elseの中へ入る)します。
短時間に多くの方からのご回答をいただき感謝しています。
只今から月曜までの間はVC++に触ることができませんので、
よろしくおねがいします。
> 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;
}
}
なかなかご説明するのが難しいため、動画として
撮影できれば望ましいのですが(´・_・`)
No.5
- 回答日時:
以下の手順で試してみましたが・・・
(1)VisualStudio2005Standardを起動
(2)VisalC++の「CLRコンソールアプリケーション」を新規に作成。
(3)作成されたコード内のmainの記述を提示されたコードに変更
(4)ifの行にブレイクポイントを設定してデバッグ実行
(5)変数「a」を「ウォッチに追加」
(6)値を「1」から「-1」に変更
(7)ステップインを実行
「retuen 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型の場合は問題なく動作しています。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Visual Basic(VBA) 数字が「0」の列を削除するため、下記のコードを実行しましたが、コンパイルエラーSubまたはFunct 3 2022/12/04 00:00
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Java java 引数 戻り値のあるメソッド 3 2023/02/12 06:23
- Visual Basic(VBA) 稀に1円合いません? Sheet1から金額と個数を貼り付ける下記コードで、金額を切り上げるコードを何 3 2022/09/05 15:11
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- Visual Basic(VBA) ユーザーフォームの表示を追加したい 2 2023/03/26 23:18
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Visual Basic(VBA) excel vbaでvlooupの変数がわかりません。 7 2022/05/30 09:35
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
フィルターかけた後、重複を除...
-
access2003 クエリSQL文に...
-
1日に1人がこなせるプログラム...
-
Exel VBA 別ブックから該当デ...
-
VBAでファイルオープン後にコー...
-
ExcelのVBAコードについて教え...
-
JANコードとPOSコードは同じ?
-
sinカーブの表示のさせ方
-
ExcelのVBAコードについて教え...
-
コンボボックス3つを連動させたい
-
pythonにてseleniumを使うも、...
-
エクセル VBA 同じ内容のセル...
-
chatgptでつくってもらったコー...
-
コンソールアプリケーションの...
-
CheckBoxのコントロール配列に...
-
エクセルに見えない文字(JISX0...
-
MessageBoxで表示される文字列...
-
WSH動作しない!!(WScript.Sle...
-
先ほど、回答者様によって教え...
-
◾️Excel VBA 統合について Cons...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
フィルターかけた後、重複を除...
-
pythonにてseleniumを使うも、...
-
ExcelのVBAコードについて教え...
-
access2003 クエリSQL文に...
-
1日に1人がこなせるプログラム...
-
ExcelのVBAコードについて教え...
-
Exel VBA 別ブックから該当デ...
-
chatgptでつくってもらったコー...
-
PreviewKeyDownイベントが2回...
-
JavaScriptの定数名が取り消し...
-
1、Rstudioで回帰直線を求める...
-
JANコードとPOSコードは同じ?
-
JavaScript|特定URLだった時、...
-
ACCESSユニオンクエリでORDER B...
-
特定行の背景色を変えたいのですが
-
変数名「cur」について
-
エクセルに見えない文字(JISX0...
-
COBOLの文法
-
Gitのクローンについて
-
Outlook VBAについて
おすすめ情報