我需要找到任意 C 表达式的最大值和最小值,该表达式没有副作用。以下宏在我的机器上工作。它们会在所有平台上工作吗?如果不行,能不能修改使之正常工作?我的目的是随后使用这些宏来实现类似于
SAFE_MUL(a,b)
的宏以替代 a*b
。 SAFE_MUL
将包括检查乘法溢出。#include <stdio.h>
#include <limits.h>
#define IS_SIGNED(exp) (((exp)*0-1) < 0)
#define TYPE_MAX_UNSIGNED(exp) ((exp)*0-1)
#define TYPE_MAX_SIGNED(exp) ( \
sizeof (exp) == sizeof (int) \
? \
INT_MAX \
: \
( \
sizeof (exp) == sizeof (long) \
? \
LONG_MAX \
: \
LLONG_MAX \
) \
)
#define TYPE_MAX(exp) ((unsigned long long)( \
IS_SIGNED (exp) \
? \
TYPE_MAX_SIGNED (exp) \
: \
TYPE_MAX_UNSIGNED (exp) \
))
#define TYPE_MIN_SIGNED(exp) ( \
sizeof (exp) == sizeof (int) \
? \
INT_MIN \
: \
( \
sizeof (exp) == sizeof (long) \
? \
LONG_MIN \
: \
LLONG_MIN \
) \
)
#define TYPE_MIN(exp) ((long long)( \
IS_SIGNED (exp) \
? \
TYPE_MIN_SIGNED (exp) \
: \
(exp)*0 \
))
int
main (void) {
printf ("TYPE_MAX (1 + 1) = %lld\n", TYPE_MAX (1 + 1));
printf ("TYPE_MAX (1 + 1L) = %lld\n", TYPE_MAX (1 + 1L));
printf ("TYPE_MAX (1 + 1LL) = %lld\n", TYPE_MAX (1 + 1LL));
printf ("TYPE_MAX (1 + 1U) = %llu\n", TYPE_MAX (1 + 1U));
printf ("TYPE_MAX (1 + 1UL) = %llu\n", TYPE_MAX (1 + 1UL));
printf ("TYPE_MAX (1 + 1ULL) = %llu\n", TYPE_MAX (1 + 1ULL));
printf ("TYPE_MIN (1 + 1) = %lld\n", TYPE_MIN (1 + 1));
printf ("TYPE_MIN (1 + 1L) = %lld\n", TYPE_MIN (1 + 1L));
printf ("TYPE_MIN (1 + 1LL) = %lld\n", TYPE_MIN (1 + 1LL));
printf ("TYPE_MIN (1 + 1U) = %llu\n", TYPE_MIN (1 + 1U));
printf ("TYPE_MIN (1 + 1UL) = %llu\n", TYPE_MIN (1 + 1UL));
printf ("TYPE_MIN (1 + 1ULL) = %llu\n", TYPE_MIN (1 + 1ULL));
return 0;
}
(exp)*0
的目的是获得一个0
,将其转换为 (exp) 的类型,但要求 exp 的类型不小于 int。 - tytya
和b
不是常量,SAFE_MUL(a,b)
似乎更有用。 - anatolyg(x+1) * y * z / (x + y)
,其中x、y、z
本身可能是任意表达式。我期望优化编译器能够在编译时评估TYPE_MAX(exp1)
,而不管x
、y
和z
的值如何。话虽如此,我同意这个问题比示例所能处理的要更普遍,原因有3个(由steve指出):(1)由无符号常量组成的表达式小于int将无法工作。 (2)涉及浮点数和双精度的表达式将无法工作。 (3)TYPE_MAX
返回的值可能小于实际值。 - tyty