web-dev-qa-db-ja.com

Cのデータ型の最小値と最大値

Cのデータ型(つまり、int、char.etc)の値の最小値と最大値を決定する関数は何ですか?

71
SuperString

次の定数を提供する limits.h を使用する必要があります(リンクされたリファレンスに従って)。

CHAR_BIT   = number of bits in a char
SCHAR_MIN  = minimum value for a signed char
SCHAR_MAX  = maximum value for a signed char
UCHAR_MAX  = maximum value for an unsigned char
CHAR_MIN   = minimum value for a char
CHAR_MAX   = maximum value for a char
MB_LEN_MAX = maximum multibyte length of a character accross locales
SHRT_MIN   = minimum value for a short
SHRT_MAX   = maximum value for a short
USHRT_MAX  = maximum value for an unsigned short
INT_MIN    = minimum value for an int
INT_MAX    = maximum value for an int
UINT_MAX   = maximum value for an unsigned int
LONG_MIN   = minimum value for a long
LONG_MAX   = maximum value for a long
ULONG_MAX  = maximum value for an unsigned long
LLONG_MIN  = minimum value for a long long
LLONG_MAX  = maximum value for a long long
ULLONG_MAX = maximum value for an unsigned long long

U*_MINは明らかな理由で省略されています(符号なしの型の最小値は0です)。

同様に、 float.h は、floatおよびdoubleタイプの制限を提供します。

-FLT_MAX = most negative value of a float
FLT_MAX  = max value of a float
-DBL_MAX = most negative value of a double
DBL_MAX  = max value of a double
-LDBL_MAX = most negative value of a long double
LDBL_MAX = max value of a long double

floats.hの記事を注意深く読む必要がありますが、floatdoubleは規定された最小値と最大値を保持できますが、各型がデータを表現できる精度は一致しません保存しようとしていますか。特に、非常に小さな部分を添付して非常に大きな数を格納することは困難です。したがって、float.hは、floatまたはdoubleが実際に特定の数値を表すことができるかどうかを判別するのに役立つ他のいくつかの定数を提供します。

87
Mark Elliot

「しかし、グリフ」、「最大が最終的に変更される可能性のある不透明(OPAQUE)型の最大値を決定しなければならない場合はどうすればよいですか?」あなたは続けるかもしれない:「もしそれが私がコントロールしていないライブラリのtypedefなら?」

ソリューションを作成するのに数時間を費やしただけだったので、あなたが尋ねてくれてうれしいです(実際の問​​題を解決しなかったので、それを捨てなければなりませんでした)。

この便利なmaxofマクロを使用して、有効な整数型のサイズを決定できます。

#define issigned(t) (((t)(-1)) < ((t) 0))

#define umaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \
                    (0xFULL << ((sizeof(t) * 8ULL) - 4ULL)))

#define smaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \
                    (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL)))

#define maxof(t) ((unsigned long long) (issigned(t) ? smaxof(t) : umaxof(t)))

次のように使用できます。

int main(int argc, char** argv) {
    printf("schar: %llx uchar: %llx\n", maxof(char), maxof(unsigned char));
    printf("sshort: %llx ushort: %llx\n", maxof(short), maxof(unsigned short));
    printf("sint: %llx uint: %llx\n", maxof(int), maxof(unsigned int));
    printf("slong: %llx ulong: %llx\n", maxof(long), maxof(unsigned long));
    printf("slong long: %llx ulong long: %llx\n",
           maxof(long long), maxof(unsigned long long));
    return 0;
}

必要に応じて、それらのマクロの前に '(t)'を投げて、求めている型の結果を得ることができます。警告を避けるためにキャストする必要はありません。

27
Glyph

最大任意の値符号なし整数型:

  • _((t)~(t)0)_ //ほとんどすべての状況で機能する汎用式。

  • _(~(t)0)_ //タイプtのサイズが_unsigned int_以上であることがわかっている場合。 (このキャストは型の昇格を強制します。)

  • _((t)~0U)_ //タイプtがわかっている場合、_unsigned int_よりもサイズが小さくなります。 (このキャストは、_unsigned int_- type式_~0U_が評価された後に型を降格します。)

最大任意の値符号付き整数型:

  • t型の符号なしバリアントがある場合、_((t)(((unsigned t)~(unsigned t)0)>>1))_を使用すると、必要な最速の結果が得られます。

  • それ以外の場合は、これを使用します(提案のため@ vinc17に感謝):_(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)_

最小任意の値signed整数型:

マシンの署名された番号表現を知っている必要があります。ほとんどのマシンは2の補数を使用するため、-(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-1が機能します。

マシンが2の補数を使用しているかどうかを検出するには、_(~(t)0U)_と_(t)(-1)_が同じものを表しているかどうかを検出します。

したがって、上記と組み合わせて:

_(-(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-(((~(t)0U)==(t)(-1)))
_

符号付き整数型の最小値を提供します。

例:_size_t_の最大値(別名_SIZE_MAX_マクロ)は_(~(size_t)0)_として定義できます。 Linuxカーネルソースコード _SIZE_MAX_マクロをこのように定義します。

ただし、1つのcaveat:これらの式はすべて、型キャストまたはsizeof演算子のいずれかを使用するため、これらはいずれもプリプロセッサー条件(_#if_ ... _#Elif_ ... _#endif_など)。

(@ chuxと@ vinc17からの提案を組み込むために回答が更新されました。両方ともありがとうございます。)

5
Explorer09
#include<stdio.h>

int main(void)
{
    printf("Minimum Signed Char %d\n",-(char)((unsigned char) ~0 >> 1) - 1);
    printf("Maximum Signed Char %d\n",(char) ((unsigned char) ~0 >> 1));

    printf("Minimum Signed Short %d\n",-(short)((unsigned short)~0 >>1) -1);
    printf("Maximum Signed Short %d\n",(short)((unsigned short)~0 >> 1));

    printf("Minimum Signed Int %d\n",-(int)((unsigned int)~0 >> 1) -1);
    printf("Maximum Signed Int %d\n",(int)((unsigned int)~0 >> 1));

    printf("Minimum Signed Long %ld\n",-(long)((unsigned long)~0 >>1) -1);
    printf("Maximum signed Long %ld\n",(long)((unsigned long)~0 >> 1));

    /* Unsigned Maximum Values */

    printf("Maximum Unsigned Char %d\n",(unsigned char)~0);
    printf("Maximum Unsigned Short %d\n",(unsigned short)~0);
    printf("Maximum Unsigned Int %u\n",(unsigned int)~0);
    printf("Maximum Unsigned Long %lu\n",(unsigned long)~0);

    return 0;
}
4
rahul gupta

ヘッダーファイル limits.h は、標準整数型のさまざまな制限とパラメーターに展開されるマクロを定義します。

3
Prasoon Saurav

limits.h および float.h のこれらのページを見てください。これらは標準cライブラリの一部として含まれています。

3
Nixuz

署名の有無にかかわらず、任意のタイプの最小値と最大値を返すマクロをいくつか作成しました。

#define MAX_OF(type) \
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU))
#define MIN_OF(type) \
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL)

サンプルコード:

#include <stdio.h>
#include <sys/types.h>
#include <inttypes.h>

#define MAX_OF(type) \
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU))
#define MIN_OF(type) \
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL)

int main(void)
{
    printf("uint32_t = %lld..%llu\n", MIN_OF(uint32_t), MAX_OF(uint32_t));
    printf("int32_t = %lld..%llu\n", MIN_OF(int32_t), MAX_OF(int32_t));
    printf("uint64_t = %lld..%llu\n", MIN_OF(uint64_t), MAX_OF(uint64_t));
    printf("int64_t = %lld..%llu\n", MIN_OF(int64_t), MAX_OF(int64_t));
    printf("size_t = %lld..%llu\n", MIN_OF(size_t), MAX_OF(size_t));
    printf("ssize_t = %lld..%llu\n", MIN_OF(ssize_t), MAX_OF(ssize_t));
    printf("pid_t = %lld..%llu\n", MIN_OF(pid_t), MAX_OF(pid_t));
    printf("time_t = %lld..%llu\n", MIN_OF(time_t), MAX_OF(time_t));
    printf("intptr_t = %lld..%llu\n", MIN_OF(intptr_t), MAX_OF(intptr_t));
    printf("unsigned char = %lld..%llu\n", MIN_OF(unsigned char), MAX_OF(unsigned char));
    printf("char = %lld..%llu\n", MIN_OF(char), MAX_OF(char));
    printf("uint8_t = %lld..%llu\n", MIN_OF(uint8_t), MAX_OF(uint8_t));
    printf("int8_t = %lld..%llu\n", MIN_OF(int8_t), MAX_OF(int8_t));
    printf("uint16_t = %lld..%llu\n", MIN_OF(uint16_t), MAX_OF(uint16_t));
    printf("int16_t = %lld..%llu\n", MIN_OF(int16_t), MAX_OF(int16_t));
    printf("int = %lld..%llu\n", MIN_OF(int), MAX_OF(int));
    printf("long int = %lld..%llu\n", MIN_OF(long int), MAX_OF(long int));
    printf("long long int = %lld..%llu\n", MIN_OF(long long int), MAX_OF(long long int));
    printf("off_t = %lld..%llu\n", MIN_OF(off_t), MAX_OF(off_t));

    return 0;
}
3
craig65535

幅が少なくともunsigned intの1つである符号なし整数型tの最大値を取得するには(そうでない場合、整数の昇格で問題が発生します):~(t) 0。短い型もサポートしたい場合は、別のキャスト(t) ~(t) 0を追加できます。

整数型tが符号付きの場合、パディングビットがないと仮定すると、以下を使用できます。

((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1)

この式の利点は、未知のまたは利用できない可能性のあるt(またはより大きな型)のいくつかの符号なしバージョンに基づいていないことです(uintmax_tでさえ、非標準の拡張では不十分な場合があります)。 6ビットの例(実際には読みやすくするために不可能です):

010000  (t) 1 << (sizeof(t) * CHAR_BIT - 2)
001111  - 1
011110  * 2
011111  + 1

2の補数では、最小値は最大値の反対のマイナス1です(ISO C標準で許可されている他の整数表現では、これはちょうど最大値の反対です)。

注:使用するバージョンを決定するために符号付きを検出するには、(t) -1 < 0は任意の整数表現で動作し、符号付き整数型には1(true)、符号なし整数型には0(false)を与えます。したがって、以下を使用できます。

(t) -1 < 0 ? ((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1) : (t) ~(t) 0
2
vinc17

整数データ型のMINおよびMAX値は、以下のライブラリ関数を使用せずに計算でき、同じロジックを他の整数型short、int、longに適用できます。

printf("Signed Char : MIN -> %d & Max -> %d\n", ~(char)((unsigned char)~0>>1), (char)((unsigned char)~0 >> 1));
printf("Unsigned Char : MIN -> %u & Max -> %u\n", (unsigned char)0, (unsigned char)(~0));
0
Arjun