このページでは、C言語
における型の最大値および最小値を調べる方法について解説していきます。
C言語
の変数で扱える値の最大値と最小値は型によって異なります。ですので、short
型の変数と long
型の変数とでは扱える値の最大値と最小値は異なります。
そして、その最大値よりも大きい値や最小値よりも小さい値を扱おうとすると、処理結果や計算結果が意図したものになりません。
これにより、「式は正しいのに計算結果がおかしい」という現象が発生してしまいます。
例えば、下記は int
型の最大値を超えてしまったために計算結果がおかしくなる例です。一度はこういった現象を経験したことがあるのではないでしょうか?
int a, b, c;
int ans;
a = 10000;
b = 10000;
c = 10000;
ans = a * b * c;
/* -727379968が表示されてしまう */
printf("%d\n", ans);
こういった計算結果がおかしくなる現象を防ぐためには、型で扱える値の最大値と最小値をしっかり把握し、計算結果がおかしくならないように変数の型をしっかり選択する必要があります。
ただ、そもそも型で扱える値の最大値と最小値を知らなければ、この型の選択のしようがありませんね!
ということで、このページでは、型を適切に選択するために必要になる「型の最大値と最小値の調べ方」について解説していきたいと思います!
と思った方おられるかもしれません…。
確かにググれば型の最大値や最小値の情報は調べられるかもしれませんが、実は型の最大値や最小値は処理系依存であり、環境によって異なる可能性があります。
つまり、ググって調べた最大値や最小値の情報は、あなたの環境では当てはまらない可能性があります。
ですので、こういった型の最大値や最小値に関しては、ご自身の環境で調べるのが一番無難です。そのため、このページでは最大値・最小値そのものではなく、それらの値の「調べ方」について解説していきたいと思います。
Contents
整数型の最大値と最小値は limits.h
のマクロを利用して調べる
では、型で扱える値の最大値と最小値の調べ方について解説していきたいと思います。
若干ですが、整数型と浮動小数点型とでは最大値と最小値を調べる方法が異なりますので、まずは整数型の場合の調べ方について解説していきます。
整数型の各型の最大値と最小値に関しては、標準ヘッダーである limits.h
にマクロとして定義されています(#define
されている)。
ですので、limits.h
を読み解けば各型の最大値と最小値を調べる事ができます。
ただ、limits.h
に最大値と最小値の値が直接記載されているとは限らないので(最大値と最小値の実際の値は他のヘッダーファイルに記載されていたりする可能性がある)、limits.h
を読むよりも、limits.h
で定義されているマクロを printf
で表示してやる方が手っ取り早く最大値と最小値を調べる事ができると思います。
ですので、このページでは、マクロを printf
で表示することで最大値と最小値を調べる方法を解説していきたいと思います。
limits.h
には、各整数型の最大値と最小値を表すマクロとして下記のものが定義されています(★マークのついているマクロは環境によっては定義されていない可能性があるので注意してください)。
したがって、調べたい型に応じたマクロを下記から選び、それを printf
で表示してやることで、その型の最大値や最小値を調べる事ができます。
例えば int
型の最大値を調べたいのであれば、printf("%d", INT_MAX);
を実行してやれば良いです(型に応じて printf
に指定する変換指定も %d
から変更する必要があるので注意してください)。
CHAR_MIN
:char
型の最小値CHAR_MAX
:char
型の最大値UCHAR_MAX
:unsigned char
型の最大値SHRT_MIN
:short int
型の最小値SHRT_MAX
:short int
型の最大値USHRT_MAX
:unsigned short int
型の最大値INT_MIN
:int
型の最小値INT_MAX
:int
型の最大値UINT_MAX
:unsigned int
型の最大値LONG_MIN
:long int
型の最小値LONG_MAX
:long int
型の最大値ULONG_MAX
:unsigned long int
型の最大値★LLONG_MIN
:long long int
型の最小値★LLONG_MAX
:long long int
型の最大値★ULLONG_MAX
:unsigned long long int
型の最大値★LONG_LONG_MIN
:long long int
型の最小値★LONG_LONG_MAX
:long long int
型の最大値★ULONG_LONG_MAX
:unsigned long long int
型の最大値★
必要なマクロのみを printf
で表示してやれば調べたい型の最大値や最小値を調べることはできるのですが、せっかくなので上記のマクロの全てを表示するソースコードを下記に用意ておきました。
#include <stdio.h>
#include <limits.h>
int main(void) {
/* char型の最小値と最大値 */
printf("CHAR_MIN = %d\n", CHAR_MIN);
printf("CHAR_MAX = %d\n", CHAR_MAX);
/* unsigned char型の最大値 */
printf("UCHAR_MAX = %d\n", UCHAR_MAX);
/* short int型の最小値と最大値 */
printf("SHRT_MIN = %d\n", SHRT_MIN);
printf("SHRT_MAX = %d\n", SHRT_MAX);
/* unsigned short int型の最大値 */
printf("USHRT_MAX = %d\n", USHRT_MAX);
/* int型の最小値と最大値 */
printf("INT_MIN = %d\n", INT_MIN);
printf("INT_MAX = %d\n", INT_MAX);
/* unsigned int型の最大値 */
printf("UINT_MAX = %u\n", UINT_MAX);
/* long int型の最小値と最大値 */
printf("LONG_MIN = %ld\n", LONG_MIN);
printf("LONG_MAX = %ld\n", LONG_MAX);
/* unsigned long int型の最大値 */
printf("ULONG_MAX = %lu\n", ULONG_MAX);
#ifdef LLONG_MIN /* LLONG_MINが定義されている場合のみ表示 */
/* long long int型の最小値と最大値 */
printf("LLONG_MIN = %lld\n", LLONG_MIN);
printf("LLONG_MAX = %lld\n", LLONG_MAX);
/* unsigned long long int型の最大値 */
printf("ULLONG_MAX = %llu\n", ULLONG_MAX);
#endif
#ifdef LONG_LONG_MIN /* LONG_LONG_MINが定義されている場合のみ表示 */
/* long long int型の最小値と最大値 */
printf("LONG_LONG_MIN = %lld\n", LONG_LONG_MIN);
printf("LONG_LONG_MAX = %lld\n", LONG_LONG_MAX);
/* unsigned long long int型の最大値 */
printf("ULONG_LONG_MAX = %llu\n", ULONG_LONG_MAX);
#endif
return 0;
}
上記のマクロ一覧で★マークを付けている “定義されていない可能性のあるマクロ” に関しては、定義されていない場合は表示を飛ばすようにしています(#ifdef
を使って定義されているかどうかを確認するようにしている)。
参考までに、私の環境で上記ソースコードのプログラムを実行した時の実行結果を下記に載せておきます。
CAHAR_MIN = -128 CAHAR_MAX = 127 UCAHAR_MAX = 255 SHRT_MIN = -32768 SHRT_MAX = 32767 USHRT_MAX = 65535 INT_MIN = -2147483648 INT_MAX = 2147483647 UINT_MAX = 4294967295 LONG_MIN = -9223372036854775808 LONG_MAX = 9223372036854775807 ULONG_MAX = 18446744073709551615 LLONG_MIN = -9223372036854775808 LLONG_MAX = 9223372036854775807 ULLONG_MAX = 18446744073709551615 LONG_LONG_MIN = -9223372036854775808 LONG_LONG_MAX = 9223372036854775807 ULONG_LONG_MAX = 18446744073709551615
ただし、前述のように、型の最大値や最小値は環境によって異なりますので、是非ご自身の環境で上記ソースコードをコンパイルし、プログラムを実行して最大値や最小値を調べてみてください。
浮動小数点数型の最大値と最小値は float.h
のマクロを利用して調べる
浮動小数点数型、すなわち float
型・double
型・long double
型に関しても “ほぼ” 同様の方法で最大値と最小値を調べる事ができます。
要はマクロの定義値を表示してやれば最大値と最小値を調べる事ができます。
ただし、浮動小数点数の型の最大値と最小値に関しては limits.h
ではなく float.h
でマクロが定義されています。ですので、浮動小数点数の型の最大値と最小値を調べる際は、float.h
をインクルードする必要がありますので注意してください。
また、浮動小数点数の場合、最小値を表すマクロで定義されているのは、”0
を含まない正の値の最小値” である点に注意が必要です。
例えば後述で紹介する FLT_MIN
は、float
型で扱える “0
を含まない正の値” の最小値(言い換えれば、float
型で扱える 0
に一番近い正の値)を定義するマクロです。
したがって、単に FLT_MIN
を表示するだけでは負の値を考慮した float
型で扱える最小値を調べることができません。
ただ、浮動小数点数の場合、最大値の符号をマイナスにしたものが最小値となりますので、最大値を示すマクロの定義値の符号をマイナスにしたものを表示することで、最小値を調べることができます。
例えば float
型であれば、FLT_MAX
の符号をマイナスにしたもの、すなわち -FLT_MAX
を表示してやれば良いです。
浮動小数点数の場合は、最大値の符号をマイナスにすることで最小値を得ることができますが、整数型の場合は最大値の符号をマイナスにしても最小値を得ることができない可能性が高いので注意してください
これは整数型の場合は、負の値の表現方法に “2の補数” が用いられているからです
負の値の表現方法に “2の補数” が用いられていない環境もあるかもしれませんが、ほぼ全ての環境では負の値の表現方法に “2の補数” が用いられています
float.h
には、各浮動小数点数型の最大値と最小値を表すマクロとして下記のものが定義されています(★マークのついているマクロは環境によっては定義されていない可能性があるので注意してください)。
ただし、前述の通り、これらのマクロで定義されている値は全て、0
を含まない正の値に対するものであることに注意してください。
FLT_MIN
:float
型の最小値FLT_MAX
:float
型の最大値DBL_MIN
:double
型の最小値DBL_MAX
:double
型の最大値LDBL_MAX
:long double
型の最大値★LDBL_MIN
:long double
型の最小値★
上記のマクロを利用して浮動小数点数の型の最大値と最小値を表示するソースコードは下記のようになります。前述の通り、最小値は最大値の符号をマイナスにすることで取得しています。
#include <stdio.h>
#include <float.h>
int main(void) {
/* float型の最小値と最大値 */
printf("FLT_MIN = %e\n", -FLT_MAX);
printf("FLT_MAX = %e\n", FLT_MAX);
/* double型の最小値と最大値 */
printf("DBL_MIN = %e\n", -DBL_MAX);
printf("DBL_MAX = %e\n", DBL_MAX);
#ifdef LDBL_MAX/* LDBL_MAXが定義されている場合のみ表示 */
/* long double型の最小値と最大値 */
printf("LDBL_MIN = %Le\n", -LDBL_MAX);
printf("LDBL_MAX = %Le\n", LDBL_MAX);
#endif
return 0;
}
上記のマクロ一覧で★マークを付けている “定義されていない可能性のあるマクロ” に関しては、定義されていない場合は表示を飛ばすようにしています(#ifdef
を使って定義されているかどうかを確認するようにしている)。
また、上記では printf
の変換指定に %e
や %Le
を指定して “指数表記” で表示していますが、変換指定を %f
や %Lf
にすれば “実数表記” で表示することもできます。ただし、桁数が膨大になるので注意してください。
参考までに、私の環境で上記ソースコードのプログラムを実行した時の実行結果を下記に載せておきます。
FLT_MIN = -3.402823e+38 FLT_MAX = 3.402823e+38 DBL_MIN = -1.797693e+308 DBL_MAX = 1.797693e+308 LDBL_MIN = -1.189731e+4932 LDBL_MAX = 1.189731e+4932
整数型の時と同様に、型の最大値や最小値は環境によって異なりますので、是非ご自身の環境で上記ソースコードをコンパイルし、プログラムを実行して最大値や最小値を調べてみてください。
スポンサーリンク
参考:自力で最大値と最小値を求める方法
ここまで最大値と最小値をマクロを利用して調べてきましたが、整数型の型の最大値や最小値であれば、ビット演算を利用することで自力で型の最大値や最小値を求めることも可能です。
ビット演算については下記ページで解説していますので、ご存知ない方は下記ページを参照していただければと思います。
C言語のビット演算(論理演算)について解説最大値や最小値を扱う場合は、ここまで解説してきたようにマクロを利用する方が良いです。
ですが、ビット演算によりどんなことが出来るのかを知ることもできると思いますので、参考までにビット演算を利用して自力で整数型の最大値や最小値を求める方法について紹介しておきます。
ただし、ここで紹介する方法は、下記を前提とした環境でのみで有効な方法になります
- 1バイト = 8ビット
- 負の値の表現方法 = 2の補数
ほとんどの環境では上記に当てはまると思いますが、環境によってはこの方法が使えない場合があるので注意してください
求め方は、「符号ありの整数型」と「符号なしの整数型」とで異なります。
まず「符号ありの整数型」における最小値と最大値を求める方法について解説します。
符号ありの整数型の場合、ビット単位で考えると、最小値は必ず最上位ビットのみが 1
で、他のビットが 0
の値となります。
10・・・・・000
したがって、最上位ビットのみを 1
、他のビットを 0
とした値を変数に格納することにより、最小値を求めることができます。
また、最大値は必ず最上位ビットのみが 0
で、他のビットが 1
となります。
01・・・・・111
したがって、最小値を格納した変数に対して NOT 演算(各ビットの 0
と 1
を逆転させる演算)を実行してやれば、最大値を求めることができます。
以上の考え方に基づいた、符号ありの整数型の型の最小値と最大値を求めるプログラムのソースコードは、下記のようになります。
#include <stdio.h>
int main(void) {
long int max, min, one;
unsigned int top_bit;
/* 1をoneに格納しておく(型の整合性をとるため) */
one = 1;
/* 最上位ビットの位置を計算 */
top_bit = sizeof(max) * 8 - 1;
/* 最上位ビットのみを1にする */
min = one << (top_bit);
/* 最上位ビットのみを0にする */
max = ~min;
/* 結果を表示 */
printf("max = %ld\n", max);
printf("min = %ld\n", min);
return 0;
}
上記は long int
型の最大値と最小値を求めるものになっていますが、求めたい最大値と最小値の型に応じて max
・min
・one
の型を変更してやれば、他の型の最大値と最小値も求めることができます(printf
の変換指定も型に応じて変更する必要があるので注意が必要です)。
簡単にソースコードの解説をしておきます。
まず、型ごとに最上位ビットの位置が異なりますので、下記により型に応じた最上位ビットの位置を求めるようにしています。
/* 最上位ビットの位置を計算 */
top_bit = sizeof(max) * 8 - 1;
sizeof(変数名)
により、その変数の型のサイズをバイト単位で取得することができます。さらに *8
を行うことで、そのサイズをビット単位に変換することができます(1バイト = 8ビット)。
最上位ビットの位置は、そのビット単位のサイズよりも 1
小さい位置となりますので、最後に -1
を行っています。
あとは前述で解説したように、最上位ビットのみを 1
とする値をシフト演算で算出して最小値を min
に格納し、さらに min
に対する NOT 演算の結果を max
に格納することで最大値を求めています。
各演算の意味等は下記ページをご参照しただければと思います。
C言語のビット演算(論理演算)について解説続いて符号なしの整数型の最大値の求め方について解説していきます。
符号なしの整数型の場合、ビット単位で考えると、最大値は必ず全てのビットが 1
の値となります。
11・・・・・111
また整数型の場合、0
はビット単位で考えると、全てのビットが 0
の値となります。
したがって、0
を格納した変数に対して NOT 演算を行うことで、符号なしの整数型に対する最大値を求めることができます。
以上の考え方に基づいた、符号なしの整数型の型の最小値と最大値を求めるプログラムのソースコードは、下記のようになります。
#include <stdio.h>
int main(void) {
unsigned long int max, zero;
/* zeroの全ビットを0にする */
zero = 0;
/* 全ビットを1にした値をmaxに格納 */
max = ~zero;
/* 結果を表示 */
printf("max = %lu\n", max);
return 0;
}
上記は unsigned long int
型の最大値を求めるものになっていますが、求めたい最大値の型に応じて max
と zero
の型を変更してやれば、他の型の最大値も求めることができます(printf
の変換指定も型に応じて変更する必要があるので注意が必要です)。
こちらに関しては処理自体が簡単ですので、ソースコードの解説は省略させていただきます。
まとめ
このページでは、C言語
における各型の最大値および最小値を調べる方法について解説しました!
各型の最大値および最小値は、ヘッダーにマクロとして定義されていますので、そのマクロの値を表示してやることで、最大値と最小値を調べることができます。
また、値を調べるだけでなく、そのマクロをソースコード上に記述することで、そのマクロを各型の最大値・最小値として扱うこともできます(もちろん変数に代入することも可能)。
整数型と浮動小数点数型では、上記のマクロが定義されているヘッダーファイルが異なるので注意してください。
- 整数型:
limits.h
- 浮動小数点数型:
float.h
また、各型の最大値と最小値は処理系依存であり、使用するコンパイラ等によって値が異なる可能性があります。
このページでも参考として各型の最大値と最小値を載せていますが異なる可能性があるため、ぜひご自身の環境で、最大値と最小値を確認しておくことをオススメします!
オススメの参考書(PR)
C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!
まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。
- 参考書によって、解説の仕方は異なる
- 読み手によって、理解しやすい解説の仕方は異なる
ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?
それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。
なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。
特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。
もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!
入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。
https://daeudaeu.com/c_reference_book/