【C言語】型の最大値と最小値を調べる(limits.h・float.h)

C言語で型の最大値と最小値を調べる方法の解説ページアイキャッチ

このページにはプロモーションが含まれています

このページでは、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);

こういった計算結果がおかしくなる現象を防ぐためには、型で扱える値の最大値と最小値をしっかり把握し、計算結果がおかしくならないように変数の型をしっかり選択する必要があります。

ただ、そもそも型で扱える値の最大値と最小値を知らなければ、この型の選択のしようがありませんね!

ということで、このページでは、型を適切に選択するために必要になる「型の最大値と最小値の調べ方」について解説していきたいと思います!

いや、ググれば最大値と最小値くらい調べられるんじゃないの?

と思った方おられるかもしれません…。

確かにググれば型の最大値や最小値の情報は調べられるかもしれませんが、実は型の最大値や最小値は処理系依存であり、環境によって異なる可能性があります。

つまり、ググって調べた最大値や最小値の情報は、あなたの環境では当てはまらない可能性があります。

ですので、こういった型の最大値や最小値に関しては、ご自身の環境で調べるのが一番無難です。そのため、このページでは最大値・最小値そのものではなく、それらの値の「調べ方」について解説していきたいと思います。

整数型の最大値と最小値は 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_MINchar 型の最小値
  • CHAR_MAXchar 型の最大値
  • UCHAR_MAXunsigned char 型の最大値
  • SHRT_MINshort int 型の最小値
  • SHRT_MAXshort int 型の最大値
  • USHRT_MAXunsigned short int 型の最大値
  • INT_MINint 型の最小値
  • INT_MAXint 型の最大値
  • UINT_MAXunsigned int 型の最大値
  • LONG_MINlong int 型の最小値
  • LONG_MAXlong int 型の最大値
  • ULONG_MAXunsigned long int 型の最大値★
  • LLONG_MINlong long int 型の最小値★
  • LLONG_MAXlong long int 型の最大値★
  • ULLONG_MAXunsigned long long int 型の最大値★
  • LONG_LONG_MINlong long int 型の最小値★
  • LONG_LONG_MAXlong long int 型の最大値★
  • ULONG_LONG_MAXunsigned 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 を表示してやれば良いです。

MEMO

浮動小数点数の場合は、最大値の符号をマイナスにすることで最小値を得ることができますが、整数型の場合は最大値の符号をマイナスにしても最小値を得ることができない可能性が高いので注意してください

これは整数型の場合は、負の値の表現方法に “2の補数” が用いられているからです

負の値の表現方法に “2の補数” が用いられていない環境もあるかもしれませんが、ほぼ全ての環境では負の値の表現方法に “2の補数” が用いられています

float.h には、各浮動小数点数型の最大値と最小値を表すマクロとして下記のものが定義されています(★マークのついているマクロは環境によっては定義されていない可能性があるので注意してください)。

ただし、前述の通り、これらのマクロで定義されている値は全て、0 を含まない正の値に対するものであることに注意してください。

浮動小数点数型に対するマクロ
  • FLT_MINfloat 型の最小値
  • FLT_MAXfloat 型の最大値
  • DBL_MINdouble 型の最小値
  • DBL_MAXdouble 型の最大値
  • LDBL_MAXlong double 型の最大値★
  • LDBL_MINlong 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言語のビット演算(論理演算)について解説

最大値や最小値を扱う場合は、ここまで解説してきたようにマクロを利用する方が良いです。

ですが、ビット演算によりどんなことが出来るのかを知ることもできると思いますので、参考までにビット演算を利用して自力で整数型の最大値や最小値を求める方法について紹介しておきます。

MEMO

ただし、ここで紹介する方法は、下記を前提とした環境でのみで有効な方法になります

  • 1バイト = 8ビット
  • 負の値の表現方法 = 2の補数

ほとんどの環境では上記に当てはまると思いますが、環境によってはこの方法が使えない場合があるので注意してください

求め方は、「符号ありの整数型」と「符号なしの整数型」とで異なります。

まず「符号ありの整数型」における最小値と最大値を求める方法について解説します。

符号ありの整数型の場合、ビット単位で考えると、最小値は必ず最上位ビットのみが 1 で、他のビットが 0 の値となります。

10・・・・・000

したがって、最上位ビットのみを 1、他のビットを 0 とした値を変数に格納することにより、最小値を求めることができます。

また、最大値は必ず最上位ビットのみが 0 で、他のビットが 1 となります。

01・・・・・111

したがって、最小値を格納した変数に対して NOT 演算(各ビットの 01 を逆転させる演算)を実行してやれば、最大値を求めることができます。

以上の考え方に基づいた、符号ありの整数型の型の最小値と最大値を求めるプログラムのソースコードは、下記のようになります。

最大値と最小値を求める(符号あり)
#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 型の最大値と最小値を求めるものになっていますが、求めたい最大値と最小値の型に応じて maxminone の型を変更してやれば、他の型の最大値と最小値も求めることができます(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 型の最大値を求めるものになっていますが、求めたい最大値の型に応じて maxzero の型を変更してやれば、他の型の最大値も求めることができます(printf の変換指定も型に応じて変更する必要があるので注意が必要です)。

こちらに関しては処理自体が簡単ですので、ソースコードの解説は省略させていただきます。

まとめ

このページでは、C言語 における各型の最大値および最小値を調べる方法について解説しました!

各型の最大値および最小値は、ヘッダーにマクロとして定義されていますので、そのマクロの値を表示してやることで、最大値と最小値を調べることができます。

また、値を調べるだけでなく、そのマクロをソースコード上に記述することで、そのマクロを各型の最大値・最小値として扱うこともできます(もちろん変数に代入することも可能)。

整数型と浮動小数点数型では、上記のマクロが定義されているヘッダーファイルが異なるので注意してください。

  • 整数型:limits.h
  • 浮動小数点数型:float.h

また、各型の最大値と最小値は処理系依存であり、使用するコンパイラ等によって値が異なる可能性があります。

このページでも参考として各型の最大値と最小値を載せていますが異なる可能性があるため、ぜひご自身の環境で、最大値と最小値を確認しておくことをオススメします!

オススメの参考書(PR)

C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!

まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。

  • 参考書によって、解説の仕方は異なる
  • 読み手によって、理解しやすい解説の仕方は異なる

ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?

それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。

なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。

特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。

もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!

入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。

https://daeudaeu.com/c_reference_book/

同じカテゴリのページ一覧を表示