# 数值极限

< c‎ | types

### 库类型极限

定义于头文件 `<stdint.h>`
PTRDIFF_WIDTH (C23) | ptrdiff_t 类型对象的位宽 (宏常量)
PTRDIFF_MIN (C99) | ptrdiff_t 类型对象的最小值 (宏常量)
PTRDIFF_MAX (C99) | ptrdiff_t 类型对象的最大值 (宏常量)
SIZE_WIDTH (C23) | size_t 类型对象的位宽 (宏常量)
SIZE_MAX (C99) | size_t 类型对象的最大值 (宏常量)
SIG_ATOMIC_WIDTH (C23) | sig_atomic_t 类型对象的位宽 (宏常量)
SIG_ATOMIC_MIN (C99) | sig_atomic_t 类型对象的最小值 (宏常量)
SIG_ATOMIC_MAX (C99) | sig_atomic_t 类型对象的最大值 (宏常量)
WINT_WIDTH (C23) | wint_t 类型对象的位宽 (宏常量)
WINT_MIN (C99) | wint_t 类型对象的最小值 (宏常量)
WINT_MAX (C99) | wint_t 类型对象的最大值 (宏常量)
定义于头文件 `<wchar.h>`
定义于头文件 `<stdint.h>`
WCHAR_WIDTH (C23) | wchar_t 类型对象的位宽 (宏常量)
WCHAR_MIN (C99) | wchar_t 类型对象的最小值 (宏常量)
WCHAR_MAX (C99) | wchar_t 类型对象的最大值 (宏常量)

注意：自立实现可能缺少 sig_atomic_t 与/或 wint_t typedef 名，此情况下相应地缺少 `SIG_ATOMIC_*` 与/或 `WINT_*` 宏。

### 示例

    #include <stdio.h>
    #include <stdint.h>
    #include <wchar.h>

    int main(void)
    {
        printf("PTRDIFF_MIN    = %td\n", PTRDIFF_MIN);
        printf("PTRDIFF_MAX    = %+td\n", PTRDIFF_MAX);
        printf("SIZE_MAX       = %zu\n", SIZE_MAX);
        printf("SIG_ATOMIC_MIN = %+jd\n",(intmax_t)SIG_ATOMIC_MIN);
        printf("SIG_ATOMIC_MAX = %+jd\n",(intmax_t)SIG_ATOMIC_MAX);
        printf("WCHAR_MIN      = %+jd\n",(intmax_t)WCHAR_MIN);
        printf("WCHAR_MAX      = %+jd\n",(intmax_t)WCHAR_MAX);
        printf("WINT_MIN       = %jd\n", (intmax_t)WINT_MIN);
        printf("WINT_MAX       = %jd\n", (intmax_t)WINT_MAX);
    }

可能的输出：

    PTRDIFF_MIN    = -9223372036854775808
    PTRDIFF_MAX    = +9223372036854775807
    SIZE_MAX       = 18446744073709551615
    SIG_ATOMIC_MIN = -2147483648
    SIG_ATOMIC_MAX = +2147483647
    WCHAR_MIN      = -2147483648
    WCHAR_MAX      = +2147483647
    WINT_MIN       = 0
    WINT_MAX       = 4294967295

### 整数类型极限

定义于头文件 `<limits.h>`
BOOL_WIDTH (C23) | _Bool 的位宽 (宏常量)
CHAR_BIT | 字节的位数 (宏常量)
CHAR_WIDTH (C23) | char 的位宽，同 `CHAR_BIT` (宏常量)
MB_LEN_MAX | 多字节字符的最大字节数 (宏常量)
CHAR_MIN | char 的最小值 (宏常量)
CHAR_MAX | char 的最大值 (宏常量)
SCHAR_WIDTH SHRT_WIDTH INT_WIDTH LONG_WIDTH LLONG_WIDTH (C23)(C23)(C23)(C23)(C23) | 分别为 signed char、short、int、long 及 long long 的位宽 (宏常量)
SCHAR_MIN SHRT_MIN INT_MIN LONG_MIN LLONG_MIN (C99) | 分别为 signed char、short、int、long 及 long long 的最小值 (宏常量)
SCHAR_MAX SHRT_MAX INT_MAX LONG_MAX LLONG_MAX (C99) | 分别为 signed char、short、int、long 及 long long 的最大值 (宏常量)
UCHAR_WIDTH USHRT_WIDTH UINT_WIDTH ULONG_WIDTH ULLONG_WIDTH (C23)(C23)(C23)(C23)(C23) | 分别为 unsigned char、unsigned short、unsigned int、unsigned long 及 unsigned long long 的位宽 (宏常量)
UCHAR_MAX USHRT_MAX UINT_MAX ULONG_MAX ULLONG_MAX (C99) | 分别为 unsigned char、unsigned short、unsigned int、 unsigned long 及 unsigned long long 的最大值 (宏常量)

### 示例

    #include <stdio.h>
    #include <limits.h>

    int main(void)
    {
        printf("CHAR_BIT   = %d\n", CHAR_BIT);
        printf("MB_LEN_MAX = %d\n", MB_LEN_MAX);
        printf("\n");

        printf("CHAR_MIN   = %+d\n", CHAR_MIN);
        printf("CHAR_MAX   = %+d\n", CHAR_MAX);
        printf("SCHAR_MIN  = %+d\n", SCHAR_MIN);
        printf("SCHAR_MAX  = %+d\n", SCHAR_MAX);
        printf("UCHAR_MAX  = %u\n",  UCHAR_MAX);
        printf("\n");

        printf("SHRT_MIN   = %+d\n", SHRT_MIN);
        printf("SHRT_MAX   = %+d\n", SHRT_MAX);
        printf("USHRT_MAX  = %u\n",  USHRT_MAX);
        printf("\n");

        printf("INT_MIN    = %+d\n", INT_MIN);
        printf("INT_MAX    = %+d\n", INT_MAX);
        printf("UINT_MAX   = %u\n",  UINT_MAX);
        printf("\n");

        printf("LONG_MIN   = %+ld\n", LONG_MIN);
        printf("LONG_MAX   = %+ld\n", LONG_MAX);
        printf("ULONG_MAX  = %lu\n",  ULONG_MAX);
        printf("\n");

        printf("LLONG_MIN  = %+lld\n", LLONG_MIN);
        printf("LLONG_MAX  = %+lld\n", LLONG_MAX);
        printf("ULLONG_MAX = %llu\n",  ULLONG_MAX);
        printf("\n");
    }

可能的输出：

    CHAR_BIT   = 8
    MB_LEN_MAX = 16

    CHAR_MIN   = -128
    CHAR_MAX   = +127
    SCHAR_MIN  = -128
    SCHAR_MAX  = +127
    UCHAR_MAX  = 255

    SHRT_MIN   = -32768
    SHRT_MAX   = +32767
    USHRT_MAX  = 65535

    INT_MIN    = -2147483648
    INT_MAX    = +2147483647
    UINT_MAX   = 4294967295

    LONG_MIN   = -9223372036854775808
    LONG_MAX   = +9223372036854775807
    ULONG_MAX  = 18446744073709551615

    LLONG_MIN  = -9223372036854775808
    LLONG_MAX  = +9223372036854775807
    ULLONG_MAX = 18446744073709551615

### 浮点类型极限

定义于头文件 `<float.h>`
FLT_RADIX | 用于表示所有三种浮点数类型的底（整数基） (宏常量)
DECIMAL_DIG (C99) | 将 long double转换成十进制小数，再转回 long double 而保持同一值，至少需要 `DECIMAL_DIG` 位小数：此乃 long double 序列化/反序列化所需的十进制精度 (宏常量)
FLT_DECIMAL_DIG DBL_DECIMAL_DIG LDBL_DECIMAL_DIG (C11) | 将 float/double/long double 转换成十进制小数再转换回同一值，至少需要 `FLT_DECIMAL_DIG`/`DBL_DECIMAL_DIG`/`LDBL_DECIMAL_DIG` 位小数：此乃浮点值序列化/反序列化所需的十进制精度。标准定义至少为 6 、 10 、 10 ， 而 IEEE float 为 9 ， IEEE double 为 17 。（见 C++ 模仿 max_digits10 ） (宏常量)
FLT_MIN DBL_MIN LDBL_MIN | 分别为 float 、 double 及 long double 的最小正规正值 (宏常量)
FLT_TRUE_MIN DBL_TRUE_MIN LDBL_TRUE_MIN (C11) | 分别为 float 、 double 和 long double 的最小正值 (宏常量)
FLT_MAX DBL_MAX LDBL_MAX | 分别为 float 、 double 和 long double 的最大有限正值 (宏常量)
FLT_EPSILON DBL_EPSILON LDBL_EPSILON | 分别为 1.0 与下一个可表示的float 、 double 和 long double 值之差 (宏常量)
FLT_DIG DBL_DIG LDBL_DIG | 保证能从文本转换为 float/double/long double 再转换回文本，而不会发生改变或上溢出的十进制位数（细节见 C++ 模仿 digits10 ） (宏常量)
FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG | 分别为 float 、 double 和 long double 所能表示而不损失精度的，浮点尾数中的 `FLT_RADIX` 底位数 (宏常量)
FLT_MIN_EXP DBL_MIN_EXP LDBL_MIN_EXP | 分别为对应 float 、 double 和 long double 的最小负整数，使得 `FLT_RADIX` 的该数减一次幂为正规 (宏常量)
FLT_MIN_10_EXP DBL_MIN_10_EXP LDBL_MIN_10_EXP | 分别为对应 float 、 double 和 long double 的最小负整数，使得 10 的该数减一次幂为正规的 (宏常量)
FLT_MAX_EXP DBL_MAX_EXP LDBL_MAX_EXP | 分别为能够使 `FLT_RADIX` 的该整数减一次幂为可表示的有限的 float、double 与 long double 的最大正整数 (宏常量)
FLT_MAX_10_EXP DBL_MAX_10_EXP LDBL_MAX_10_EXP | 分别为能够使 10 的该整数减一次幂为可表示的有限的 float、double 与 long double 的最大正整数 (宏常量)
FLT_ROUNDS | 浮点算术的舍入模式，等于 float_round_style (宏常量)
FLT_EVAL_METHOD (C99) | 中间结果所用的扩展精度： 0 表示不使用， 1 表示用 double 替代 float ， 2 表示使用 long double (宏常量)
FLT_HAS_SUBNORM DBL_HAS_SUBNORM LDBL_HAS_SUBNORM (C11) | 类型是否支持非正规（非正规）数： -1 为不确定， 0 为不支持， 1 为支持 (宏常量)

### 示例

    #include <stdio.h>
    #include <float.h>
    #include <math.h>

    int main(void)
    {
        printf("FLT_RADIX    = %d\n", FLT_RADIX);
        printf("DECIMAL_DIG  = %d\n", DECIMAL_DIG);
        printf("FLT_MIN      = %e\n", FLT_MIN);
        printf("FLT_MAX      = %e\n", FLT_MAX);
        printf("FLT_EPSILON  = %e\n", FLT_EPSILON);
        printf("FLT_DIG      = %d\n", FLT_DIG);
        printf("FLT_MANT_DIG = %d\n", FLT_MANT_DIG);
        printf("FLT_MIN_EXP  = %d\n",  FLT_MIN_EXP);
        printf("FLT_MIN_10_EXP  = %d\n",  FLT_MIN_10_EXP);
        printf("FLT_MAX_EXP     = %d\n",  FLT_MAX_EXP);
        printf("FLT_MAX_10_EXP  = %d\n",  FLT_MAX_10_EXP);
        printf("FLT_ROUNDS      = %d\n",  FLT_ROUNDS);
        printf("FLT_EVAL_METHOD = %d\n",  FLT_EVAL_METHOD);
        printf("FLT_HAS_SUBNORM = %d\n",  FLT_HAS_SUBNORM);
    }

可能的输出：

    FLT_RADIX    = 2
    DECIMAL_DIG  = 37
    FLT_MIN      = 1.175494e-38
    FLT_MAX      = 3.402823e+38
    FLT_EPSILON  = 1.192093e-07
    FLT_DIG      = 6
    FLT_MANT_DIG = 24
    FLT_MIN_EXP  = -125
    FLT_MIN_10_EXP  = -37
    FLT_MAX_EXP     = 128
    FLT_MAX_10_EXP  = 38
    FLT_ROUNDS      = 1
    FLT_EVAL_METHOD = 1
    FLT_HAS_SUBNORM = 1

### 引用

- C17 标准（ISO/IEC 9899:2018）：

  - 5.2.4.2 Numerical limits (p: 20-27)

  - 7.20.3 Limits of other integer types (p: 215-216)

- C11 标准（ISO/IEC 9899:2011）：

  - 5.2.4.2 Numerical limits (p: 26-34)

  - 7.20.3 Limits of other integer types (p: 293-294)

- C99 标准（ISO/IEC 9899:1999）：

  - 5.2.4.2 Numerical limits (p: 21-28)

  - 7.18.3 Limits of other integer types (p: 259-260)

- C89/C90 标准（ISO/IEC 9899:1990）：

  - 2.2.4.2 Numerical limits

### 参阅