重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

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

A 回答 (8件)

#2の回答にもあるように、<limits.h>で定義されたマクロを使うのが標準的な方法です。



unsigned shortの最大値はUSHRT_MAX、unsigned intの最大値はUINT_MAX、unsigned longの最大値はULONG_MAX、unsigned long longの最大値はULLONG_MAXを使います。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
試してみたいと思います。<(_ _)>

お礼日時:2005/07/20 20:54

>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の方の方法が良いですが。
    • good
    • 0
この回答へのお礼

まとめのご意見ありがとうございました。
独学なので、皆さんにとって当たり前のことでも
知らないことが多いことを痛感しました!

大変助かりました。ありがとうございます!<(_ _)>

お礼日時:2005/07/20 21:01

すんません。

C99(のドラフトですが)を確認したところ、unsigned typeの値は2^nのmoduloであることが保証されるようでした。とほほ・・・
    • good
    • 0
この回答へのお礼

御回答ありがとうございました。
いまひとつ理解が追いついておりませんが、
取り急ぎお礼まで

お礼日時:2005/07/20 20:58

言語仕様まで確認していないのですが、「++u」がゼロになるまで回してその直前の値を最大値とするのであれば、それは「u = 0; --u;」で得られる結果と同じになりませんか? これならビット演算はいらないので2の補数表現ではない処理系でも実行でき、ループも必要ありません。



もっとも、オーバーフロー・アンダーフロー発生時の式の値や変数の値は、それが合理的な値かどうかも含めて「処理系依存」と定義されている(=無茶苦茶な値になっても文句は言えない)ような気がしますが。
    • good
    • 0

> コンパイル時に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が最大か、そうでないかしかわかりません。
    • good
    • 0
この回答へのお礼

ありがとうございます。
参考にさせていただきます<(_ _)>

お礼日時:2005/07/20 20:57

#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);
としてください。
    • good
    • 0
この回答へのお礼

再度御回答いただきましてありがとうございます。
printfも十分に理解しておりませんでした。
よくわかりました。(^^ゞ

お礼日時:2005/07/20 20:55

「正しく」という意味がよく分からないのですが(特に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 …
    • good
    • 0
この回答へのお礼

御回答ありがとうございます。URLもありがとうございました。
なるほど、いろいろあるんですね♪すばらしい。
勉強不足でさらっと理解できそうにないので、
おいおい勉強していきたいと思います。

お礼日時:2005/07/19 22:49

>変数に入りうる最大値の値を、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”

補足日時:2005/07/19 22:41
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!