
C言語で、整数型変数の扱える範囲を確認するために
以下のような処理をしているのですが、どうもうまくいきません。
変数に入りうる最大値の値を、2進数の計算ではなく
プログラム内で正しく扱われているか確認する方法はないでしょうか?
ご存知の方、教えてください<(_ _)>
宜しくお願いいたします。
**********************************************
unsigned long long I;
unsigned long A;
unsigned int B;
unsigned short C;
printf("I:%d A:%d byte B:%d byte C:%d byte \n"
,sizeof(I),sizeof(A),sizeof(B),sizeof(C));
A = B = C = 0;
for(I = 0; I <= 4294967295; I++){
A++;B++;C++;
if(I>= 4294967290 && I<= 4294967295)
printf("I:%d A:%d B:%d C:%d\n",I,A,B,C);
}
No.8
- 回答日時:
>printf("I:%d A:%d B:%d C:%d\n",I,A,B,C);
はprintf("I:%lld A:%d B:%d C:%d\n",I,A,B,C);
にしないとだめです。
A,B,Cは%dを%uに変えたほうが良いですが。
Iに関しては%lld又は%lluでないと、A,B,Cを正しく表示できません。
long longの出力は%lld又は%llu又は%llxです。
私の回答は質問に書かれたプログラムに関してです。
40億回もループさせないNo.2からNo.7の方の方法が良いですが。
まとめのご意見ありがとうございました。
独学なので、皆さんにとって当たり前のことでも
知らないことが多いことを痛感しました!
大変助かりました。ありがとうございます!<(_ _)>
No.6
- 回答日時:
言語仕様まで確認していないのですが、「++u」がゼロになるまで回してその直前の値を最大値とするのであれば、それは「u = 0; --u;」で得られる結果と同じになりませんか? これならビット演算はいらないので2の補数表現ではない処理系でも実行でき、ループも必要ありません。
もっとも、オーバーフロー・アンダーフロー発生時の式の値や変数の値は、それが合理的な値かどうかも含めて「処理系依存」と定義されている(=無茶苦茶な値になっても文句は言えない)ような気がしますが。
No.5
- 回答日時:
> コンパイル時にforループのIをインクリメントするところで
> 次のような警告が出るのですがループがうまく回らないようです。
> “warning: decimal constant is so large that it is unsigned”
これは、インクリメントでwarningが出ているのではないと思います。
ループ条件に対して言っているのだと思います。
4294967295 以下というループ条件ですが、decimalに直すと、0xffffffff (つまり -1)で、 unsigned longの変数Iと比較すると、常にループ条件は偽になりますよ、だから、コンパイラが最適化して、unsignedと解釈します。と言っているのだと思います。(適当ですけど)
for(I = 0; I <= (unsigned long)4294967275; I++)
としてみてください。
warning 出なくなります。
たぶんですけど。
あと、私見ですが、
整数型変数の扱える範囲を確認するため
というのであれば、#2の方の方法が最もスマートだと思います。
処理系に依存しますが、64bitマシンでプログラミングした際、unsigned longの最大値が0xffffffffffffffffだったことがあります。
#2の方のプログラムでしたら、どんな場合でも最大値が出力されます。
#1の方のプログラムでは、ループ条件に4294967295が使われていますので、4294967295が最大か、そうでないかしかわかりません。
No.2
- 回答日時:
「正しく」という意味がよく分からないのですが(特にunsigned 系だと、最大値と最小値は紙一重です)、最大値は下記の方法で入らないでしょうか?(ビット演算だけどね)
unsigned long ul;
ul = 0;
ul = ~ul;
処理系によっては結果は変わるかもしれませんし、いま手元にコンパイラがないので確認できませんが。
ただ、今調べていて limits.h というヘッダにはその処理系の最大値・最小値が定義されていることを思い出しました。
ここで定義されている定義済み定数を使えば、処理系の差から来るトラブルを最小にしながらプログラムをかけます。
http://www9.plala.or.jp/sgwr-t/c/sec13.html
また、printf() での出力指示子もなかなか奥の深いものがありますので研究してみてください。
参考URL:http://www.linux.or.jp/JM/html/LDP_man-pages/man …
御回答ありがとうございます。URLもありがとうございました。
なるほど、いろいろあるんですね♪すばらしい。
勉強不足でさらっと理解できそうにないので、
おいおい勉強していきたいと思います。

No.1
- 回答日時:
>変数に入りうる最大値の値を、2進数の計算ではなく
>プログラム内で正しく扱われているか確認する方法はない>でしょうか?
この意味が不明ですが、要はA,B,Cがとりうる最大の値をプログラムで確認したいということでしょうか。
unsigned long A,A1;
unsigned int B,B1;
unsigned short C,C1;
として
for(I = 0; I <= 4294967295; I++){
A1=A;
B1=B;
C1=C;
A++;B++;C++;
if (A==0)の時 A1が最大値なのでこれを印字
if (B==0)の時 B1が最大値なのでこれを印字
if (C==0)の時 C1が最大値なのでこれを印字
}
ではいかがでしょうか。
符号無し整数の最大値に1を加えると0に戻る性質を利用しています。
この回答への補足
さっそくご回答ありがとうございます。
処理してみますと、unsigned shortのCは正しく出力されるのですが
ABに関しては以下のようになってしまいます。
A=-1
B=-1
C=65535
コンパイル時にforループのIをインクリメントするところで
次のような警告が出るのですがループがうまく回らないようです。
“warning: decimal constant is so large that it is unsigned”
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
画面を強制的に再描画させる方法
-
CSVファイルの特定の行だけを読...
-
VBAで3秒だけ時間を止めたい
-
乱数の桁数指定、または範囲指定。
-
null 参照の例外が実行時に発生...
-
範囲指定したセルを1つずつ飛...
-
ループを回すという意味は何で...
-
流れ図(フローチャート)が分か...
-
VBAでの一時停止と再開の方法
-
「偶数・奇数の和」のフローチ...
-
メッセージループを調べすぎてC...
-
多重ループの抜けだし方
-
DOSコマンドのループ内のTIMEコ...
-
VBA for i=1 to lastrow
-
データベースをEOFまでループさ...
-
EXCEL VBA ユーザーフォームの...
-
「VC++6」ウィンドウの再描画
-
Javaでゲーム
-
UWSCに制限時間を付けたいです
-
Do whileでExitせず、ループの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
画面を強制的に再描画させる方法
-
UWSCの終了の仕方
-
CSVファイルの特定の行だけを読...
-
範囲指定したセルを1つずつ飛...
-
UWSCに制限時間を付けたいです
-
Escキーを押すと、中断する時と...
-
乱数の桁数指定、または範囲指定。
-
VBA for i=1 to lastrow
-
流れ図(フローチャート)が分か...
-
DOSコマンドのループ内のTIMEコ...
-
pythonでファイルのコメント行...
-
素数表について。
-
VBAでの一時停止と再開の方法
-
「偶数・奇数の和」のフローチ...
-
DoEventsが必要な理由について
-
vb.netです。2次元配列の要素を...
-
Do whileでExitせず、ループの...
-
ループフリー
-
エクセルの当番表を作っていま...
-
VBAで3秒だけ時間を止めたい
おすすめ情報