我想用#define制作一个简单的宏来返回两个较小的数字。
我怎样才能在C中这样做?提出一些想法,看看你是否可以使它更加混淆。
答案 0 :(得分:12)
典型地:
#define min(a, b) (((a) < (b)) ? (a) : (b))
警告这会评估最小值两次,这是recent question中发生灾难的原因。
但你为什么要混淆呢?
这个结果将结果存储在变量中,并且只评估每个参数一次。它基本上是一个穷人的内联函数+声明:
#define min(t, x, a, b) \
t x; \
{ \
t _this_is_a_unique_name_dont_use_it_plz_0_ = a; \
t _this_is_a_unique_name_dont_use_it_plz_1_ = b; \
x = _this_is_a_unique_name_dont_use_it_plz_0_ < \
_this_is_a_unique_name_dont_use_it_plz_1_ ? \
_this_is_a_unique_name_dont_use_it_plz_0_ : \
_this_is_a_unique_name_dont_use_it_plz_1_ ; \
}
使用它像:
min(int, x, 3, 4)
/* x is an int, equal to 3
Just like doing:
int x = min(3, 4);
Without double evaluation.
*/
答案 1 :(得分:5)
而且,仅仅是为了它,它是一个GNU C的例子:
#define MAX(a,b) ({ \
typeof(a) _a_temp_; \
typeof(b) _b_temp_; \
_a_temp_ = (a); \
_b_temp_ = (b); \
_a_temp_ = _a_temp_ < _b_temp_ ? _b_temp_ : _a_temp_; \
})
它没有被混淆,但我认为这适用于任何类型,任何上下文,(几乎,见评论)任何参数等;如果你能想到任何反例,请更正。
答案 2 :(得分:3)
当然,您可以使用#define,但为什么要这样做?使用#define(即使是括号)的问题在于,使用这样的代码会得到意想不到的结果(好吧,你实际上不会这样做,但它说明了问题)。
int result = min(a++, b++);
如果你使用的是C ++而不是C,最好使用内联函数,它(i)避免多次评估参数,(ii)类型安全(你甚至可以提供其他类型值的版本) ,如无符号,双重或字符串)。
inline int min(int a, int b) { return (a < b) ? a : b; }
答案 3 :(得分:3)
我认为这种方法很可爱:
#define min(a, b) (((a) + (b) - fabs((a) - (b))) * 0.5)
答案 4 :(得分:1)
我想用#define制作一个简单的宏来返回两个较小的数字。
我想在数字 浮点时添加解决方案。
考虑数字是浮点数,其中一个数字是not-a-number。然后a < b
的结果始终为false
,无论其他数字的值如何。
// the result is `b` when either a or b is NaN
#define min(a, b) (((a) < (b)) ? (a) : (b))
可能希望结果如下所示&#34; NaN参数被视为缺失数据&#34;。 C11脚注#242
a NaN | b NaN | a < b | min
-------+---------+---------+---------------
No | No | No | b
No | No | Yes | a
No | Yes | . | a
Yes | No | . | b
Yes | Yes | . | either a or b
使用C中的宏执行此操作将简单地包装支持上表的fmin()
函数。当然代码通常应该直接使用fmin()
函数。
#include <math.h>
#define my_fmin(a, b) (fmin((a), (b))
请注意,fmin(0.0, -0.0)
可能会返回0.0
或-0.0
。它们都具有相等的值。
答案 5 :(得分:0)
如果我只是试图轻率地模糊这一点,我可能会选择以下内容:
#define min(a,b) ((a) + ((b) < (a) ? (b) - (a) : 0))
我认为Doynax的解决方案也非常可爱。关于宏观论证被多次评估的常见保留。
答案 6 :(得分:-7)
稍微混淆一下,试试这个:
#define MIN(a,b) ((((a)-(b))&0x80000000) >> 31)? (a) : (b)
基本上,它会减去它们,并将符号位视为1或0。 如果减法导致负数,则第一个参数更小。