C宏至少有两个数字

时间:2010-03-16 22:51:40

标签: c c-preprocessor minimum

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

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

7 个答案:

答案 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。 如果减法导致负数,则第一个参数更小。