C宏至少有两个数字

我想用#define创建一个简单的宏来返回两个较小的数字。

我怎么能在C中这样做? 提出一些想法,看看你是否可以使它更加模糊。

稍微混淆,试试这个:

#define MIN(a,b) ((((a)-(b))&0x80000000) >> 31)? (a) : (b) 

基本上,它会减去它们,并将符号位视为1或0。 如果减法导致负数,则第一个参数更小。

典型:

 #define min(a, b) (((a) < (b)) ? (a) : (b)) 

请注意,这至少会评估两次,这是最近一个问题中发生灾难的原因。

但是你为什么要混淆呢?


这个结果将结果存储在变量中,并且只评估每个参数一次。 它基本上是一个穷人的内联函数+声明:

 #define min(t, x, a, b) \ tx; \ { \ 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. */ 

而且,仅仅是为了它,它是一个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_; \ }) 

它没有被混淆,但我认为这适用于任何类型,在任何情况下,(几乎,见评论)任何参数等; 如果你能想到任何反例,请更正。

当然,你可以使用#define,但你为什么要这样做? 使用#define(即使是括号)的问题在于,使用这样的代码会得到意想不到的结果(好吧,你实际上不会这样做,但它说明了问题)。

 int result = min(a++, b++); 

如果你使用C ++而不是C,最好使用内联函数,它(i)避免多次评估参数,(ii)类型安全(你甚至可以提供其他类型值的版本,如unsigned ,双或字符串)。

 inline int min(int a, int b) { return (a < b) ? a : b; } 

我觉得这个方法很可爱:

#define min(a, b) (((a) + (b) - fabs((a) - (b))) * 0.5)

我想用#define创建一个简单的宏来返回两个较小的数字。

我希望在数字浮点时添加解决方案。


考虑当数字是浮点数时,其中一个数字不是数字 。 然后,无论其他数字的值如何, a < b的结果总是为false

 // the result is `b` when either a or b is NaN #define min(a, b) (((a) < (b)) ? (a) : (b)) 

可能希望结果如下,其中“NaN参数被视为缺失数据”。 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  #define my_fmin(a, b) (fmin((a), (b)) 

请注意, fmin(0.0, -0.0)可能返回0.0-0.0 。 它们都具有同等价值

如果我只是想轻易地混淆这个,我可能会用以下的东西:

 #define min(a,b) ((a) + ((b) < (a) ? (b) - (a) : 0)) 

我觉得Doynax的解决方案也非常可爱。 关于宏观论点被多次评估的通常保留。