下のソースはビットの操作なんですけど、オーバーフローの判定をするにはどうしたら良いのでしょうか?今そこで悩んでるんです。
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
//変数の宣言
unsigned char X;
unsigned char Y;
//Xの入力
printf("00からFFまでのHEX値をXに入力 X = ");
scanf("%d", &X);
printf("\n");
//Yの入力
printf("00からFFまでのHEX値をYに入力 Y = ");
scanf("%d", &Y);
printf("\n");
//結果の表示
printf("Xのビット毎補数 結果は => %#x\n", ~X);
printf("XとYのAND 結果は => %#X\n", X & Y);
printf("XとYのOR 結果は => %#x\n", X | Y);
printf("XとYのXOR 結果は => %#x\n", X ^ Y);
return 0;
}
そのビット演算じゃオーバーフローなんてしませんよ。
>unsigned char X;
>scanf("%d", &X);
個人的にはunsgined charに対し %d を使っているのが怖い。
そこらへんどう動いているのか知らないけどねん。
単にオーバーフローしているのか確かめたいなら動かしてみればいい。
アクセスバイオレーションになるか、なんかの変数値がおかしくなるはずだ。
あれ?オーバーフローって言うのはアセンブラで言うキャリーフラグとかだと思ったけど違うの?ひょっとしてXに256や1000が入力された場合って意味?
確かにビット演算と「判定」って言ってるあたり
キャリーフラグの話っぽいなぁ。
バッファーオーバーフローの話だと思ってた。
>そのビット演算じゃオーバーフローなんてしませんよ。
も納得。
>ひょっとしてXに256や1000が入力された場合って意味?
話の流れから察するにキーボードで入力する値の話よね。
%d指定しているんだから、
0でも255でもオーバーフロー起こしそうじゃない?
printf("Xのビット毎補数 結果は => %#x\n", ~X);
↑メッセージで示された範囲値を入れて、ここで表示される値が
「0xffff…」となるから…? と、勝手な想像。
>そのビット演算じゃオーバーフローなんてしませんよ。
確かにしないww
オーバーフローフラグ?
たとえば 127 + 1 = 128 だ。
でも8ビット符号ありでは -128 になる。
これがオーバーフロー(アンダーフロー)。
キャリーフラグとは違う。
しかし質問はunsigned charでANDやORなんだよな。
× オーバーフロー(アンダーフロー)
○ オーバーフローフラグ
まぁ確かにバッファオーバーフローしそうなソースではあるが。
重要なものをかきわすれてましたね。すみません。返事遅くなりまして。
これがただしいソースです。やっぱりオーバーフローの判定わかりません。
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
//変数の宣言
unsigned char X;
unsigned char Y;
//Xの入力
printf("00からFFまでのHEX値をXに入力 X = ");
scanf("%d", &X);
printf("\n");
//Yの入力
printf("00からFFまでのHEX値をYに入力 Y = ");
scanf("%d", &Y);
printf("\n");
//結果の表示
printf("Xのビット毎補数 結果は => %#x\n", ~X);
printf("XとYのAND 結果は => %#x\n", X & Y);
printf("XとYのOR 結果は => %#x\n", X | Y);
printf("XとYのXOR 結果は => %#x\n", X ^ Y);
printf("XをYビット左シフトした 結果は=> %#x\n", X << Y);
return 0;
}
オーバーフローしないとか
それともバッファーオーバーのことか
といった意見に対して
答えずに話を進められると不快なんですけど。不快なんですけど。
動作確認していないから正しいか知らんよ。
キャリーフラグの意味でのオーバーとして
unsigned char A = X << Y;
unsigned char B = A >> Y;
if(X != B) {
オーバーした
}
ANDやORは計算結果の桁数が増えたりしないからオーバーはしない。
>重要なものをかきわすれてましたね。
あとソースの説明もしてほしい。
人のソース見るの面倒だし
ソースがあれば説明なくても相手に伝わるとは限らないし。
動作確認していないから正しいか知らんよ(無責任だけど)。
if((Y >= 8 && X >= 1) || (Y == 7 && X >= 2) || 省略 || (X>=256)) {
オーバーした
}
ネタっぽいのでいいならこんなんで。
if( (X!=0) && ((Y>7)|| ((~( (1<<(8-Y)) -1)) & X) != 0 )) {
オーバーしそう
}
ちなみにCでキャリーフラグを取る関数は無いみたいなので(DOSの時代はあった気もするけど…)、その辺りをスマートにしたいならインラインアセンブラしかないですね。
それが嫌なら上記のようにif文の羅列しかないかと。
ためしにこれ↓を実行してみたらランタイムエラーで怒られた
int
_tmain(int argc, _TCHAR* argv[])
{
unsigned char X;
scanf_s(_T("%d"), &X);
return 0;
}
エラー内容
Run-Time Check Failure #2 - Stack around the variable 'X' was corrupted.
あの、16進数を二桁表示するのってどうすればいいんですか?
さきにそれをしようとしたのですがわからなくて。
あと、補数を表示するのもいまいちうまくいってない気がするんです。
どうすればいいのでしょうか?
printf("%02x\n", x);
ただしxが2桁に収まる値に限る。
納まらないなら以下のように。
printf("%02x\n", x & 255);
いまいちうまくいってない気がするとか言われても判らん。
unsigned char だから 8bit しか入らない = 演算結果も常に 8bit/16進2桁 で表示される
と思っている?前半は正しく、後半は間違い。
unsigned char x=123;
unsigned char y=~x;
printf("%#x\n", y);
printf("%#x\n", ~x);
ということで結果が違うわけだ。
この辺を理解するには「 C/C++ は char では演算しない」という仕様を理解する必要がある
言語規格書では汎整数拡張とか呼ばれているわけで。
http://ja.wikipedia.org/wiki/%E6%B1%8E%E6%95%B4%E6%95%B0%E6%8B%A1%E5%BC%B5
既に指摘があるように &255 すれば16進2桁になる。
俺の例では y=~x; を実行する際に &255 演算が隠れているわけだ。
つーか、もっと言えばビット演算やキャリーフラグなんて初心者が手を出すものじゃない。予想外に難しい論理?とかアセンブラみたいなものが出てきて手に負えなくなる。
中級者になってから勉強するぐらいで十分。
ツイート | ![]() |