C中数据types的最小值和最大值

什么是函数来确定在C中的数据types的值(即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由于显而易见的原因被省略(任何无符号types具有最小值0)。

同样, float.h提供了floatdoubletypes的限制:

 -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的文章,尽pipefloatdouble可以保持规定的最小值和最大值,但每种types可以表示数据的精度可能与您要存储的值floats.h 。 尤其是,要存储分数极less的特大号码很困难。 所以float.h提供了许多其他的常量来帮助你判断一个floatdouble可以代表一个特定的数字。

“但字形”,我听到你问:“如果我必须确定一个最大值可能最终变化的不透明types的最大值? 你可能会继续说:“如果这是我无法控制的图书馆的typedef呢?

我很高兴你问,因为我花了几个小时来制作一个解决scheme(然后我不得不扔掉,因为它没有解决我的实际问题)。

您可以使用这个方便的maxofmacros来确定任何有效整数types的大小。

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

如果你愿意的话,你可以在这些macros的前面放一个“(t)”,这样就可以给出你所要求的types的结果,而且你不必为了避免警告而进行投射。

头文件limits.h定义了扩展到标准整数types的各种限制和参数的macros。

看一下limits.h和float.h中的这些页面,它们是标准c库的一部分。

任何无符号整型的 最大值(~(t)0)

任何有符号整型的 最大值 :如果你有一个types为t的无符号variables, ((t)((~(unsigned t)0)>>1))会给你你需要的最快结果源代码如下)。 否则,你应该使用(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))

任何签名整数types的 最小值 :您必须知道您的机器的签名号码表示。 大多数机器使用2的补码,因此-(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1将适用于您。

要检测你的机器是否使用二进制补码,检测(~(t)0U)(t)(-1)代表相同的东西。 所以,结合以上:

 ((~(t)0U) == (t)(-1) ? -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1 : -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))) 

会给你任何签名的整数types的最小值。 (实际上,如果知道2的补码表示,实际上还有其他的表示forms,例如(t)(1ULL<<(sizeof(t)*CHAR_BIT-1))应该等于(t)(-(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1) 。)

例如:(〜(size_t)0)给你size_t的最大值。 (猜猜看,这是在Linux内核源代码中如何定义SIZE_MAX。)

一个需要注意的是:所有这些expression式都使用types转换,所以在预处理器条件(#if … #elif … #endif之类的)中不起作用。

我写了一些返回任何types的最小值和最大值的macros,而不pipe签名如何:

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

任何整型数据types的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)); 

为了得到无符号整数typest的最大值,其宽度至less是unsigned int (否则得到整数提升的问题): ~(t) 0

如果整数typest是有符号的,假设没有填充位,可以使用:

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

这个公式的优点是它不是基于一些未经签名的t (或更大的types)版本,可能是未知的或不可用的(即使uintmax_t对于非标准的扩展也许是不够的)。 6位示例(实际上不可能,仅为了便于阅读):

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

在二进制补码中,最小值与最大值减1相反(在ISO C标准允许的其他整数表示中,这与最大值正好相反)。

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