- ベストアンサー
変数の扱える範囲
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); }
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
#2の回答にもあるように、<limits.h>で定義されたマクロを使うのが標準的な方法です。 unsigned shortの最大値はUSHRT_MAX、unsigned intの最大値はUINT_MAX、unsigned longの最大値はULONG_MAX、unsigned long longの最大値はULLONG_MAXを使います。
その他の回答 (7)
- TT414
- ベストアンサー率18% (72/384)
>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の方の方法が良いですが。
お礼
まとめのご意見ありがとうございました。 独学なので、皆さんにとって当たり前のことでも 知らないことが多いことを痛感しました! 大変助かりました。ありがとうございます!<(_ _)>
- xcrOSgS2wY
- ベストアンサー率50% (1006/1985)
すんません。C99(のドラフトですが)を確認したところ、unsigned typeの値は2^nのmoduloであることが保証されるようでした。とほほ・・・
お礼
御回答ありがとうございました。 いまひとつ理解が追いついておりませんが、 取り急ぎお礼まで
- xcrOSgS2wY
- ベストアンサー率50% (1006/1985)
言語仕様まで確認していないのですが、「++u」がゼロになるまで回してその直前の値を最大値とするのであれば、それは「u = 0; --u;」で得られる結果と同じになりませんか? これならビット演算はいらないので2の補数表現ではない処理系でも実行でき、ループも必要ありません。 もっとも、オーバーフロー・アンダーフロー発生時の式の値や変数の値は、それが合理的な値かどうかも含めて「処理系依存」と定義されている(=無茶苦茶な値になっても文句は言えない)ような気がしますが。
- jagd-doga
- ベストアンサー率31% (14/45)
> コンパイル時に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が最大か、そうでないかしかわかりません。
お礼
ありがとうございます。 参考にさせていただきます<(_ _)>
- tatsu99
- ベストアンサー率52% (391/751)
#1です。 >ABに関しては以下のようになってしまいます。 >A=-1 >B=-1 符号無し整数は%uを使用します。%dは符号付き整数です。 printf("I:%d A:%d B:%d C:%d\n",I,A,B,C); を printf("I:%d A:%lu B:%u C:%d\n",I,A,B,C); としてください。
お礼
再度御回答いただきましてありがとうございます。 printfも十分に理解しておりませんでした。 よくわかりました。(^^ゞ
- Somali_Shinji
- ベストアンサー率14% (45/305)
「正しく」という意味がよく分からないのですが(特にunsigned 系だと、最大値と最小値は紙一重です)、最大値は下記の方法で入らないでしょうか?(ビット演算だけどね) unsigned long ul; ul = 0; ul = ~ul; 処理系によっては結果は変わるかもしれませんし、いま手元にコンパイラがないので確認できませんが。 ただ、今調べていて limits.h というヘッダにはその処理系の最大値・最小値が定義されていることを思い出しました。 ここで定義されている定義済み定数を使えば、処理系の差から来るトラブルを最小にしながらプログラムをかけます。 http://www9.plala.or.jp/sgwr-t/c/sec13.html また、printf() での出力指示子もなかなか奥の深いものがありますので研究してみてください。
お礼
御回答ありがとうございます。URLもありがとうございました。 なるほど、いろいろあるんですね♪すばらしい。 勉強不足でさらっと理解できそうにないので、 おいおい勉強していきたいと思います。
- tatsu99
- ベストアンサー率52% (391/751)
>変数に入りうる最大値の値を、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”
お礼
回答ありがとうございました。 試してみたいと思います。<(_ _)>