在C中确定数据类型(即int,char.etc)的最小值和最大值的函数是什么?
答案 0 :(得分:85)
您需要使用提供以下常量的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
是否可以代表特定的数字。
答案 1 :(得分:25)
“但是字形”,我听到你问,“如果我必须确定最大可能最终会改变的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)',这样他们就会给你一个你要问的类型的结果,而你不需要做避免警告。
答案 2 :(得分:5)
最大值:
((t)~(t)0)
//通用表达式几乎可以在所有表达式中使用
情况。
(~(t)0)
//如果您知道您的类型t
的大小等于或大于
unsigned int
。 (此演员类型促销。)
((t)~0U)
//如果您知道类型t
的尺寸小于。unsigned int
unsigned int
。 (此演员表会在~0U
- 类型之后输入降级
评估表达式t
。)
任何签名整数类型的最大值:
如果您有((t)(((unsigned t)~(unsigned t)0)>>1))
类型的无符号变体,(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)
会为您提供所需的最快结果。
否则,请使用此功能(感谢@ vinc17提供建议):-(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-1
任何签名整数类型的最小值:
您必须知道机器的签名号码表示。大多数机器使用2的补码,因此(~(t)0U)
将适合您。
要检测您的机器是否使用2的补码,请检测(t)(-1)
和(-(((1ULL<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-(((~(t)0U)==(t)(-1)))
是否代表同一事物。
所以,结合以上:
size_t
将为您提供任何有符号整数类型的最小值。
作为示例:SIZE_MAX
(例如,(~(size_t)0)
宏)的最大值可以定义为SIZE_MAX
。 Linux kernel source code以这种方式定义sizeof
宏。
一个警告但是:所有这些表达式都使用类型转换或#if
运算符,因此这些都不适用于预处理器条件(#elif
... {{ 1}} ... #endif
等。)
(更新了答案,以便纳入来自@ chux和@ vinc17的建议。谢谢两位。)
答案 3 :(得分:4)
implements JavascriptExecutor
答案 4 :(得分:3)
头文件limits.h
定义了扩展到各种限制和标准整数类型参数的宏。
答案 5 :(得分:3)
答案 6 :(得分:3)
我写了一些宏,它们返回任何类型的最小值和最大值,无论签名如何:
#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;
}
答案 7 :(得分:2)
要获得无符号整数类型t
的最大值,其宽度至少为unsigned int
之一(否则会出现整数提升问题):~(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
在二进制补码中,最小值与最大值相反,减去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
答案 8 :(得分: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));