5

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

我怎么能在 C 中做到这一点?提出一些想法,看看你是否也可以让它变得更加模糊。

4

7 回答 7

12

通常:

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

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

但是你为什么要混淆它呢?


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

#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.
*/
于 2010-03-16T22:53:26.033 回答
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_; \
    })

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

于 2010-03-17T21:13:45.993 回答
3

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

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

如果您使用的是 C++ 而不是 C,那么使用内联函数肯定会更好,它 (i) 避免多次评估参数,并且 (ii) 是类型安全的(您甚至可以提供采用其他类型值的版本,例如 unsigned ,双精度或字符串)。

inline int min(int a, int b) { return (a < b) ? a : b; }
于 2010-03-16T23:14:10.973 回答
3

我觉得这个方法很可爱:

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

于 2010-03-19T22:40:41.600 回答
1

我想用#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 <math.h>
#define my_fmin(a, b) (fmin((a), (b))

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

于 2017-09-19T18:23:48.617 回答
0

如果我只是想稍微混淆一下,我可能会使用以下内容:

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

我认为 Doynax 的解决方案也很可爱。通常对不止一次评估宏参数的保留。

于 2010-03-19T23:00:17.297 回答
-6

对于稍微混淆,试试这个:

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

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

于 2010-03-16T23:23:26.383 回答