我想知道在C中是否有某种方式来反省一种类型的最大值。
例如,我有一个名为a
的变量,它是unsigned short
...
{
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
是一个宏,它使用某种方法来获取基于类型的范围(这是静态的)。
其他资格赛......
char/short/int/long/long long/float/double
注意:这适用于生成的代码,显然包括<lmits.h>
,使用USHRT_MAX
和CHAR_MAX
几乎在所有情况下都能正常工作。
答案 0 :(得分:6)
我从来没有做过c11,但它确实有一个可以帮助你的功能,根据维基百科称为&#34;类型通用表达式&#34;。据我所知,你可以做_Generic(a, int: INT_MAX, long: LONG_MAX, default: SOME_MANINGFUL_DEFAULT_VALUE)
。这将检查a的类型,并根据其类型选择要评估的表达式,这将是类型泛型表达式的结果。
它不是最好的解决方案,但你要做的就是拥有一个使用_Generic的宏,并处理你感兴趣的所有算术类型。
GCC 4.9(https://gcc.gnu.org/wiki/C11Status)似乎支持它。
维基百科页面可能比我更好地解释它:http://en.wikipedia.org/wiki/C11_(C_standard_revision)
答案 1 :(得分:2)
这是一个使用GCC __builtin_types_compatible_p
的解决方案,虽然它有效,但它有以下缺点。
示例代码:
#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;
}
答案 2 :(得分:2)
此示例使用基于@Pedro Henrique A. Oliveira的答案的C11泛型,
注意,它可以添加更多类型(ssize_t size_t intptr_t
...等)。
#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;
}
答案 3 :(得分:0)
如果您愿意对数字表示做出假设而不是陷入标准(支持您几乎不可能关心的体系结构),那么您可以将~0
填入目标变量中输入(对于无符号类型),然后将该值赋给max
。对于签名(或可能已签名)的类型,您填写~0
并查看a < 0
。如果是这样,假设2的补码并从那里开始。您已经确定long long
可以保存您关注的任何类型的任何值,因此您可以在粉碎它之前存储a
的副本(假设这个技巧只能在{{}}下工作1}})。
我刚刚发布了一个测试示例来验证这一切都通过普通优化(使用gcc)减少到常量:
a