Cのデータ型(つまり、int、char.etc)の値の最小値と最大値を決定する関数は何ですか?
次の定数を提供する 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
の記事を注意深く読む必要がありますが、float
とdouble
は規定された最小値と最大値を保持できますが、各型がデータを表現できる精度は一致しません保存しようとしていますか。特に、非常に小さな部分を添付して非常に大きな数を格納することは困難です。したがって、float.h
は、float
またはdouble
が実際に特定の数値を表すことができるかどうかを判別するのに役立つ他のいくつかの定数を提供します。
「しかし、グリフ」、「最大が最終的に変更される可能性のある不透明(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)'を投げて、求めている型の結果を得ることができます。警告を避けるためにキャストする必要はありません。
最大任意の値符号なし整数型:
_((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からの提案を組み込むために回答が更新されました。両方ともありがとうございます。)
#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;
}
ヘッダーファイル limits.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)
サンプルコード:
#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;
}
幅が少なくとも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
整数データ型の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));