VC++での条件分岐
解決済
回答 4
投稿
- 評価
- クリップ 0
- VIEW 1,505
VC++での条件分岐
Visual Studio 2005 Professionalを未だに使用しています。
久しぶりのプログラミングのせいか、自分でミスが見つからないため、
何がいけないのか教えて頂けないでしょうか?
後述するプログラムで、条件分岐で真となり上の方が実行されると思ったのですが、
実際はelseが実行されてしまいます。(ステップ実行で確認)
該当のソースコード
static int test_test(void)
{
char sSrcData[256];
char *ptr1;
char *ptr2;
ptr1 = sSrcData;
ptr2 = sSrcData;
sSrcData[0] = 0xEF;
sSrcData[1] = 0xBB;
sSrcData[2] = 0xBF;
if( (sSrcData[0] == 0xEF) && (sSrcData[1] == 0xBB) && (sSrcData[2] == 0xBF) ){
ptr1+=3;
ptr2+=3;
}else{
// ここにきてしまう
printf("kitayo\n");
}
return(0);
}
アセンブラの情報を見ると以下になっています。
static int test_test(void)
{
00413E10 push ebp
00413E11 mov ebp,esp
00413E13 sub esp,1E4h
00413E19 push ebx
00413E1A push esi
00413E1B push edi
00413E1C lea edi,[ebp-1E4h]
00413E22 mov ecx,79h
00413E27 mov eax,0CCCCCCCCh
00413E2C rep stos dword ptr es:[edi]
00413E2E mov eax,dword ptr [___security_cookie (417000h)]
00413E33 xor eax,ebp
00413E35 mov dword ptr [ebp-4],eax
char sSrcData[256];
char *ptr1;
char *ptr2;
ptr1 = sSrcData;
00413E38 lea eax,[ebp-108h]
00413E3E mov dword ptr [ebp-114h],eax
ptr2 = sSrcData;
00413E44 lea eax,[ebp-108h]
00413E4A mov dword ptr [ebp-120h],eax
sSrcData[0] = 0xEF;
00413E50 mov byte ptr [ebp-108h],0EFh
sSrcData[1] = 0xBB;
00413E57 mov byte ptr [ebp-107h],0BBh
sSrcData[2] = 0xBF;
00413E5E mov byte ptr [ebp-106h],0BFh
if( (sSrcData[0] == 0xEF) && (sSrcData[1] == 0xBB) && (sSrcData[2] == 0xBF) ){
00413E65 movsx eax,byte ptr [ebp-108h]
00413E6C cmp eax,0EFh
00413E71 jne test_test+9Fh (413EAFh)
00413E73 movsx eax,byte ptr [ebp-107h]
00413E7A cmp eax,0BBh
00413E7F jne test_test+9Fh (413EAFh)
00413E81 movsx eax,byte ptr [ebp-106h]
00413E88 cmp eax,0BFh
00413E8D jne test_test+9Fh (413EAFh)
ptr1+=3;
00413E8F mov eax,dword ptr [ebp-114h]
00413E95 add eax,3
00413E98 mov dword ptr [ebp-114h],eax
ptr2+=3;
00413E9E mov eax,dword ptr [ebp-120h]
00413EA4 add eax,3
00413EA7 mov dword ptr [ebp-120h],eax
}else{
00413EAD jmp test_test+0B6h (413EC6h)
// ここにきてしまう
printf("kitayo\n");
00413EAF mov esi,esp
00413EB1 push offset string "kitayo\n" (4157D4h)
00413EB6 call dword ptr [__imp__printf (4182F4h)]
00413EBC add esp,4
00413EBF cmp esi,esp
00413EC1 call @ILT+350(__RTC_CheckEsp) (411163h)
}
return(0);
00413EC6 xor eax,eax
}
何が間違っているか教えて頂けないでしょうか?
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+4
こんにちは。
Visual C++のchar型は符号付き8ビットですので、0x80以上0xFF以下の値は負になってしまいます。
ということは、一度char型変数へ0xEFを設定し、これをint型へ戻すと符号拡張されて内部表現的には0xFFFFFFEFとなってしまいます。
しかし、char型変数へ設定していない0xEFはint型のままですので0x000000EFです。
従って、等しくなりません。
char型変数を使った時に時々ハマる罠ですね。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
char型の sSrcData と 0xEF という最上位ビットが1の意味ディエイトデータを比較しています。
お使いのコンパイラは、sSrcData の内容を符号拡張(movsxインストラクション)を使い、eax
レジスタに代入して、比較を行っています。
つまり 0xFFFFFFEF と 0x000000EF を比較しています。sSrcData を unsigned にするとか、
比較の時は、両オペランドを unsigned でキャストする等して、符号拡張が起こらないように
する必要があるかと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
0xEF
はint型として評価されます。式の中にcharとintのように異なる型が混在する場合は、サイズの大きい方に暗黙の型変換が行われます。この場合、char型のデータがint型に型変換されることになるのですが、char型の変数に設定された0xEFは-17
なのでint型に変換しても符号拡張により-17となります。
対処方法としては右辺をcharでキャストすれば良いですが、よりスマートな実装としては、char型定数として定義する方法がお勧めです。
下記コードを追加し、それぞれの値をBOM8_1~3
に置き換えてみてください。
const char BOM8_1 = 0xEF;
const char BOM8_2 = 0xBB;
const char BOM8_3 = 0xBF;
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
よくわかりませんが…
unsigned char ならいけるんじゃ?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/04/22 22:48
0xFEは1バイトしか書いてなくてもint型なのを失念していました。
遠い昔に同じ事を教えて貰った事を思い出しました。