オーバーフローの判定をするには?


pk  2008-06-18 02:00:33  No: 68573

下のソースはビットの操作なんですけど、オーバーフローの判定をするにはどうしたら良いのでしょうか?今そこで悩んでるんです。

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


とおりすがこ  2008-06-18 02:19:10  No: 68574

そのビット演算じゃオーバーフローなんてしませんよ。


そだ  2008-06-18 02:29:24  No: 68575

>unsigned char X;
>scanf("%d", &X);

個人的にはunsgined charに対し %d を使っているのが怖い。
そこらへんどう動いているのか知らないけどねん。


そだ  2008-06-18 09:09:37  No: 68576

単にオーバーフローしているのか確かめたいなら動かしてみればいい。
アクセスバイオレーションになるか、なんかの変数値がおかしくなるはずだ。


とおりすがこ  2008-06-18 09:22:38  No: 68577

あれ?オーバーフローって言うのはアセンブラで言うキャリーフラグとかだと思ったけど違うの?ひょっとしてXに256や1000が入力された場合って意味?


そだ  2008-06-18 09:44:06  No: 68578

確かにビット演算と「判定」って言ってるあたり
キャリーフラグの話っぽいなぁ。
バッファーオーバーフローの話だと思ってた。

>そのビット演算じゃオーバーフローなんてしませんよ。
も納得。

>ひょっとしてXに256や1000が入力された場合って意味?
話の流れから察するにキーボードで入力する値の話よね。
%d指定しているんだから、
0でも255でもオーバーフロー起こしそうじゃない?


ん?  2008-06-18 10:04:10  No: 68579

printf("Xのビット毎補数  結果は => %#x\n", ~X);

↑メッセージで示された範囲値を入れて、ここで表示される値が
「0xffff…」となるから…?  と、勝手な想像。

>そのビット演算じゃオーバーフローなんてしませんよ。
確かにしないww


wclrp ( 'o')  2008-06-18 14:48:05  No: 68580

オーバーフローフラグ?

たとえば 127 + 1 = 128 だ。
でも8ビット符号ありでは -128 になる。
これがオーバーフロー(アンダーフロー)。
キャリーフラグとは違う。

しかし質問はunsigned charでANDやORなんだよな。


wclrp ( 'o')  2008-06-18 14:49:22  No: 68581

× オーバーフロー(アンダーフロー)
○ オーバーフローフラグ


シャノン  2008-06-18 18:52:39  No: 68582

まぁ確かにバッファオーバーフローしそうなソースではあるが。


pk  2008-06-19 05:07:38  No: 68583

重要なものをかきわすれてましたね。すみません。返事遅くなりまして。
これがただしいソースです。やっぱりオーバーフローの判定わかりません。

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


wclrp ( 'o')  2008-06-19 05:44:27  No: 68584

オーバーフローしないとか
それともバッファーオーバーのことか
といった意見に対して
答えずに話を進められると不快なんですけど。不快なんですけど。


wclrp ( 'o')  2008-06-19 05:50:02  No: 68585

動作確認していないから正しいか知らんよ。

キャリーフラグの意味でのオーバーとして
unsigned char A = X << Y;
unsigned char B = A >> Y;
if(X != B) {
    オーバーした
}

ANDやORは計算結果の桁数が増えたりしないからオーバーはしない。


wclrp ( 'o')  2008-06-19 05:59:37  No: 68586

>重要なものをかきわすれてましたね。

あとソースの説明もしてほしい。
人のソース見るの面倒だし
ソースがあれば説明なくても相手に伝わるとは限らないし。

動作確認していないから正しいか知らんよ(無責任だけど)。
if((Y >= 8 && X >= 1) || (Y == 7 && X >= 2) || 省略 || (X>=256)) {
    オーバーした
}


そだ  2008-06-19 07:15:23  No: 68587

ネタっぽいのでいいならこんなんで。
if( (X!=0) && ((Y>7)|| ((~( (1<<(8-Y)) -1)) & X) != 0 )) {
  オーバーしそう
}


とおりすがこ  2008-06-19 09:34:05  No: 68588

ちなみにCでキャリーフラグを取る関数は無いみたいなので(DOSの時代はあった気もするけど…)、その辺りをスマートにしたいならインラインアセンブラしかないですね。
それが嫌なら上記のようにif文の羅列しかないかと。


ゴン  2008-06-19 20:53:17  No: 68589

ためしにこれ↓を実行してみたらランタイムエラーで怒られた

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.


pk  2008-06-30 06:46:04  No: 68590

あの、16進数を二桁表示するのってどうすればいいんですか?
さきにそれをしようとしたのですがわからなくて。
あと、補数を表示するのもいまいちうまくいってない気がするんです。
どうすればいいのでしょうか?


wclrp ( 'o')  2008-06-30 18:01:27  No: 68591

printf("%02x\n", x);
ただしxが2桁に収まる値に限る。

納まらないなら以下のように。
printf("%02x\n", x & 255);

いまいちうまくいってない気がするとか言われても判らん。


tetrapod  2008-06-30 18:17:13  No: 68592

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 演算が隠れているわけだ。


ななし  2008-06-30 21:18:09  No: 68593

つーか、もっと言えばビット演算やキャリーフラグなんて初心者が手を出すものじゃない。予想外に難しい論理?とかアセンブラみたいなものが出てきて手に負えなくなる。
中級者になってから勉強するぐらいで十分。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加