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
提供了float
和double
types的限制:
-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
的文章,尽pipefloat
和double
可以保持规定的最小值和最大值,但每种types可以表示数据的精度可能与您要存储的值floats.h
。 尤其是,要存储分数极less的特大号码很困难。 所以float.h
提供了许多其他的常量来帮助你判断一个float
或double
可以代表一个特定的数字。
“但字形”,我听到你问:“如果我必须确定一个最大值可能最终变化的不透明types的最大值? 你可能会继续说:“如果这是我无法控制的图书馆的typedef呢?
我很高兴你问,因为我花了几个小时来制作一个解决scheme(然后我不得不扔掉,因为它没有解决我的实际问题)。
您可以使用这个方便的maxof
macros来确定任何有效整数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; }