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

zzwlnbp8  于 2023-02-07  发布在  其他
关注(0)|答案(9)|浏览(120)

在C语言中,确定数据类型(如int、char等)的最小值和最大值的函数是什么?

xzv2uavs

xzv2uavs1#

您将需要使用limits.h,它提供了以下常量(根据链接引用):

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
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
PTRDIFF_MIN    : minimum value of ptrdiff_t
PTRDIFF_MAX    : maximum value of ptrdiff_t
SIZE_MAX       : maximum value of size_t
SIG_ATOMIC_MIN : minimum value of sig_atomic_t
SIG_ATOMIC_MAX : maximum value of sig_atomic_t
WINT_MIN       : minimum value of wint_t
WINT_MAX       : maximum value of wint_t
WCHAR_MIN      : minimum value of wchar_t
WCHAR_MAX      : maximum value of wchar_t
CHAR_BIT       : number of bits in a char
MB_LEN_MAX     : maximum length of a multibyte character in bytes

其中U*_MIN由于显而易见的原因而被省略(任何无符号类型的最小值都是0)。
类似地,float.hfloatdouble类型提供限制:

FLT_MIN    : smallest normalised positive value of a float
FLT_MAX    : largest positive finite value of a float
DBL_MIN    : smallest normalised positive value of a double
DBL_MAX    : largest positive finite value of a double
LDBL_MIN   : smallest normalised positive value of a long double
LDBL_MAX   : largest positive finite value of a long double
FLT_DIG    : the number of decimal digits guaranteed to be preserved converting from text to float and back to text
DBL_DIG    : the number of decimal digits guaranteed to be preserved converting from text to double and back to text
LDBL_DIG   : the number of decimal digits guaranteed to be preserved converting from text to long double and back to text

浮点类型是关于零对称的,所以最负的有限数是最正的有限数的反-例如float的范围从-FLT_MAXFLT_MAX
请注意,浮点类型只能精确地表示其范围内的一小部分有限的值。随着存储的绝对值变大,可以精确表示的相邻数字之间的间距也会变大。

bbuxkriu

bbuxkriu2#

"但是glyph",我听到你问,"如果我必须确定一个不透明类型的最大值,而它的最大值最终可能会改变,那该怎么办?"你可能会继续说:"如果它是一个我不控制的库中的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)',这样它们就可以给出您所请求的类型的结果,并且您不必进行强制转换来避免警告。

q35jwt9p

q35jwt9p3#

任何 * unsigned * 整型的 * 最大 * 值:

  • ((t)~(t)0)//几乎适用于所有情况的通用表达式。
  • (~(t)0)//如果你知道你的类型t等于或大于unsigned int。此施法强制类型升级。
  • ((t)~0U)//如果您知道类型t的大小等于或小于unsigned int。此强制转换在计算unsigned int类型表达式~0U之后将类型降级。

例如:size_t(又称SIZE_MAX宏)的最大值可以定义为(~(size_t)0)Linux kernel source code可以这样定义SIZE_MAX宏。
任何 * signed * 整型的 * 最大 * 值:

  • 如果你有一个t类型的无符号变量,((t)(((unsigned t)~(unsigned t)0)>>1))将提供你所需要的最快的结果。
  • 否则,使用这个(感谢@vinc17的建议):(((t)1<<(sizeof(t)*CHAR_BIT-2))-1)*2+1

任何 * 有符号 * 整型的 * 最小 * 值:
你必须知道你的机器的有符号数表示法,大多数机器使用2的补码,所以下面的方法对你来说是可行的:

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

/* Equivalent: */
(1-((t)1<<(sizeof(t)*CHAR_BIT-2)))*2-2

若要检测计算机是否使用2的补码,请检测((t)~(t)0)(t)(-1)是否表示相同的东西。* 更新(2022 - 03 - 24):* (t)应该是有符号类型。C99标准要求从有符号整数类型到无符号整数类型的转换行为。无论有符号整数类型中的值-* N * 的 * 对象表示 * 如何,将-* N * 转换为无符号整数类型始终生成1加上无符号类型的最大值减去 * N * 的值。例如,(unsigned long)(-(N))等于ULONG_MAX+1-(N)
结合以上内容,这将给出任何 * 有符号 * 整型的 * 最小 * 值:

-((((t)1<<(sizeof(t)*CHAR_BIT-2))-1)*2+1)-((t)~(t)0==(t)-1)

/* Equivalent: */
(1-((t)1<<(sizeof(t)*CHAR_BIT-2)))*2-1-((t)~(t)0==(t)-1)

不过有一点要注意所有这些表达式都使用类型转换或sizeof运算符,因此它们都不能在预处理器条件(#if ... #elif ... #endif等)中工作。

  • (已更新答案,以纳入@chux和@vinc17的建议。谢谢两位。)*
whlutmcx

whlutmcx4#

我写了一些宏,它们返回任何类型的最小值和最大值,而不管有无符号:

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

w7t8yxp55#

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

aurhwmvo

aurhwmvo6#

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

332nm8kg7#

请查看limits.hfloat.h上的这些页面,它们是标准c库的一部分。

col17t5w

col17t5w8#

要获取宽度至少为unsigned int的无符号整数类型t(否则整数提升会出现问题):~(t) 0。如果还想支持更短的类型,则可以添加另一种类型转换:(t) ~(t) 0.
如果整数类型t有符号,假设没有填充位,可以使用:

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

这个公式的优点是它不基于t的无符号版本(或更大的类型),因为无符号版本可能是未知或不可用的(即使uintmax_t也可能不足以用于非标准扩展)。

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
t9eec4r0

t9eec4r09#

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

相关问题