C中数据类型的最小值和最大值

时间:2010-01-13 01:42:58

标签: c types

在C中确定数据类型(即int,char.etc)的最小值和最大值的函数是什么?

9 个答案:

答案 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.hfloatdouble类型提供了限制:

-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提供了许多其他常量,可帮助您确定floatdouble是否可以代表特定的数字。

答案 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_MAXLinux kernel source code以这种方式定义sizeof宏。

一个警告但是:所有这些表达式都使用类型转换或#if运算符,因此这些都不适用于预处理器条件(#elif ... {{ 1}} ... #endif等。)

(更新了答案,以便纳入来自@ chux和@ vinc17的建议。谢谢两位。)

答案 3 :(得分:4)

implements JavascriptExecutor

答案 4 :(得分:3)

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

答案 5 :(得分:3)

查看limits.hfloat.h上的这些页面,它们作为标准c库的一部分包含在内。

答案 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));