带C的内省型最小/最大值
我想知道在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
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;
}