Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带C的内省型最小/最大值_C_Types_C Preprocessor - Fatal编程技术网

带C的内省型最小/最大值

带C的内省型最小/最大值,c,types,c-preprocessor,C,Types,C Preprocessor,我想知道在C语言中是否有某种方法可以反思类型的最大值 例如,我有一个名为a的变量,它是一个无符号的短 { unsigned short a; long long max = TYPEOF_MAX(a); /* now max will be USHRT_MAX */ } { signed char a; long long max = TYPEOF_MAX(a); /* now max will be CHAR_MAX */ } 其中,TYPE

我想知道在C语言中是否有某种方法可以反思类型的最大值

例如,我有一个名为
a
的变量,它是一个
无符号的短

{
    unsigned short a;
    long long max = TYPEOF_MAX(a);
    /* now max will be USHRT_MAX */
}

{
    signed char a;
    long long max = TYPEOF_MAX(a);
    /* now max will be CHAR_MAX */
}
其中,
TYPEOF_MAX
是一个宏,它使用某种方法获取基于in-type(静态)的范围

其他限定符

  • 如果仅限于几种类型,例如
    char/short/int/long/long/long/float/double
  • 这可能需要使用一些C扩展、GCC甚至C11,尽管更适合使用可移植的方法

注意:这是用于生成的代码,显然包括
,使用
USHRT\u MAX
CHAR\u MAX
在几乎所有情况下都可以正常工作。

我从未使用过c11,但根据维基百科的“类型通用表达式”,它确实有一个可以帮助您的功能。据我所知,您可以执行
\u通用(a,int:int\u MAX,long:long\u MAX,default:SOME\u MANINGFUL\u default\u VALUE)
。这将检查a的类型,并根据其类型选择要计算的表达式,该表达式将作为类型泛型表达式的结果

这不是最好的解决方案,但你所要做的就是有一个宏,它使用泛型,处理你感兴趣的所有算术类型

GCC4.9()似乎支持它


wikipedia页面可能比我解释得更好:

这是一个使用GCC的
\u内置类型\u兼容的\u p
的解决方案,虽然它可以工作,但它有以下缺点

  • 仅GCC(无MSVC)
  • 缺少的类型不会在构建时失败(而是在运行时)
  • 不能在函数外使用
  • 不被视为常量,因此不能与静态断言一起使用
示例代码:

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

#define TYPEOF_MAX(x)                                                         \
  ({                                                                          \
    typeof(x) tmp;                                                            \
    if      (__builtin_types_compatible_p(typeof(x), signed char))            \
      tmp = (typeof(x))CHAR_MAX;                                              \
    else if (__builtin_types_compatible_p(typeof(x), unsigned char))          \
      tmp = (typeof(x))UCHAR_MAX;                                             \
    else if (__builtin_types_compatible_p(typeof(x), signed short))           \
      tmp = (typeof(x))SHRT_MAX;                                              \
    else if (__builtin_types_compatible_p(typeof(x), unsigned short))         \
      tmp = (typeof(x))USHRT_MAX;                                             \
    else if (__builtin_types_compatible_p(typeof(x), signed int))             \
      tmp = (typeof(x))INT_MAX;                                               \
    else if (__builtin_types_compatible_p(typeof(x), unsigned int))           \
      tmp = (typeof(x))UINT_MAX;                                              \
    else if (__builtin_types_compatible_p(typeof(x), signed long))            \
      tmp = (typeof(x))LONG_MAX;                                              \
    else if (__builtin_types_compatible_p(typeof(x), unsigned long))          \
      tmp = (typeof(x))ULONG_MAX;                                             \
    else if (__builtin_types_compatible_p(typeof(x), float))                  \
      tmp = (typeof(x))FLT_MAX;                                               \
    else if (__builtin_types_compatible_p(typeof(x), double))                 \
      tmp = (typeof(x))DBL_MAX;                                               \
    else                                                                      \
      abort ();                                                               \
    tmp;                                                                      \
  })


int main(void)
{
    short       num_short;
    int         num_int;
    double      num_double;
    signed char num_char;


    printf("  %ld max short\n",     TYPEOF_MAX(num_short));
    printf("  %ld max int\n",       TYPEOF_MAX(num_int));
    printf("  %f  max double\n",    TYPEOF_MAX(num_double));
    printf("  %ld max char\n",      TYPEOF_MAX(num_char));
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义_MAX(x)的类型\
({                                                                          \
(x)tmp的类型\
if(uuu内置_u类型_u兼容_up(typeof(x),带符号字符))\
tmp=(x)字符的最大类型\
else if(uuu内置类型u兼容p(typeof(x),无符号字符))\
tmp=(x)型UCHAR_MAX\
else if(uuu内置类型u兼容类型u p(typeof(x),短符号))\
tmp=(x)类型的最大压力\
else if(uuu内置类型u兼容类型u p(typeof(x),无符号短))\
tmp=(x)型最大值\
else if(uuu内置类型u兼容p(typeof(x),带符号int))\
tmp=(x)的类型INT_MAX\
else if(uuu内置类型u兼容p(typeof(x),unsigned int))\
tmp=(x)类型的最大值\
else if(uuu内置类型u兼容类型u p(typeof(x),有符号长))\
tmp=(x)型长_最大值\
else if(uuu内置类型u兼容类型u p(typeof(x),无符号长))\
tmp=(x)型ULONG_MAX\
else if(uuuu内置类型u兼容类型u p(typeof(x),float))\
tmp=(x)型)最大飞行高度\
else if(uuu内置类型u兼容类型u p(typeof(x),double))\
tmp=(x的类型)DBL_MAX\
否则\
中止()\
tmp\
})
内部主(空)
{
短数;
int num_int;
双数双;
符号字符num_char;
printf(“%ld max short\n”,TYPEOF_max(num_short));
printf(“%ld max int\n”,TYPEOF_max(num_int));
printf(“%f max double\n”,TYPEOF_max(num_double));
printf(“%ld max char\n”,TYPEOF_max(num_char));
返回0;
}

如果您愿意对数字表示进行假设,而不是陷入标准(支持您几乎不可能关心的体系结构)中,您可以将
~0
填充到目标类型的变量中(对于无符号类型),然后将该值赋给
max
。对于已签名(或可能已签名)类型,请在
~0
中填充并选中
a<0
。如果是这样,假设2的补码,然后从那里开始。您已经决定
long-long
可以保存您所关心的任何类型的任何值,因此您可以在粉碎
a
之前将其保存一份(假设此技巧只在
a
的情况下有效)

我刚刚创建了一个测试示例,以验证通过普通优化(使用gcc),这一切都会减少到一个常数:

a=~0;
if(a<0)//如果a被签名,则为true
{

a^=1此示例使用基于@Pedro Henrique a.Oliveira答案的C11泛型

注意,它可以添加更多类型(
ssize\u t size\u t intptr\t
…等)

#包括
#包括
#包括
#包括
#包括
#定义_MAX(x)的类型\
_通用(x\
布尔:1\
char:char\u MAX,有符号char:SCHAR\u MAX,无符号char:UCHAR\u MAX\
有符号短路:SHRT_MAX,无符号短路:USHRT_MAX\
有符号整数:整数最大值,无符号整数:整数最大值\
签名长:长\u MAX,未签名长:长\u MAX\
签名的long-long:LLONG_-MAX,未签名的long-long:ULLONG_-MAX\
浮动:FLT_最大值,双精度:DBL_最大值)
#定义_MIN(x)的类型\
_通用(x\
布尔:0\
a = ~0;
if (a < 0)  // true if a is signed
{
    a ^= 1 << (sizeof(a) * 8 - 1);  // flip sign bit to get all 1's positive
    max = a;
    min = -a - 1;
}
else
{
    max = a;
    min = 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <float.h>
#include <stdint.h>

#define TYPEOF_MAX(x) \
    _Generic(x, \
        bool: 1, \
        char: CHAR_MAX, signed char: SCHAR_MAX, unsigned char: UCHAR_MAX, \
        signed short: SHRT_MAX, unsigned short: USHRT_MAX, \
        signed int: INT_MAX, unsigned int: UINT_MAX, \
        signed long: LONG_MAX, unsigned long: ULONG_MAX, \
        signed long long: LLONG_MAX, unsigned long long: ULLONG_MAX, \
        float: FLT_MAX, double: DBL_MAX)


#define TYPEOF_MIN(x) \
    _Generic(x, \
        bool: 0, \
        char: CHAR_MIN, signed char: SCHAR_MIN, unsigned char: 0, \
        signed short: SHRT_MIN, unsigned short: 0, \
        signed int: INT_MIN, unsigned int: 0, \
        signed long: LONG_MIN, unsigned long: 0, \
        signed long long: LLONG_MIN, unsigned long long: 0, \
        float: -FLT_MAX, double: -DBL_MAX)

/* change 100 to 1000 - static asserts work! */
_Static_assert(TYPEOF_MAX((char)4) > 100, "example check");


int main(void)
{
    short       num_short;
    int         num_int;
    double      num_double;
    signed char num_char;


    printf("  %ld max short\n",     TYPEOF_MAX(num_short));
    printf("  %ld max int\n",       TYPEOF_MAX(num_int));
    printf("  %f  max double\n",    TYPEOF_MAX(num_double));
    printf("  %ld max char\n",      TYPEOF_MAX(num_char));
    return 0;
}