【问题标题】:C Macro for minimum of two numbers最少两个数字的 C 宏
【发布时间】:2011-01-28 08:38:15
【问题描述】:

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

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

【问题讨论】:

标签: c c-preprocessor minimum


【解决方案1】:

通常:

#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.
*/

【讨论】:

  • 它应该有点模糊 - 它是为另一个认为自己是编程策划者的人准备的,这就是原因。无论如何,tnx。
  • 哪个语言的策划者?如果我们去 C++,我相信我可以尝试给他一些东西来炒他的专家面条。但是,好吧,我们可以做出什么样的假设?这些整数是我们找到的最小值吗?再说一次,也许这只是一个背景故事来欺骗我回答。 :)
  • “我可以给他一些东西来炒他的专家面条” - 很高兴听到这个消息,等待进一步的答案 xD 。顺便说一句,问题是因为在课堂上我们需要一个简单的最小函数,所以我决定使用宏,所以它看起来更 c-ish。
  • 为了更安全,我会添加另一对括号:#define min(a, b) ( ((a)
  • 值得一提的是,GCC 有 typeof 扩展名 (gcc.gnu.org/onlinedocs/gcc/Typeof.html),可以避免将类型名称作为宏参数提及。
【解决方案2】:

还有一个 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_; \
    })

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

【讨论】:

  • 这不太可能发生,但如果 ab 碰巧自己是名为 _a_temp__b_temp_ 的变量。
  • 是的,我想粘上__LINE__,但似乎不值得努力;要是有一个__UNIQUE__ 宏就好了……
  • 你应该得到一个更好的分数,请参阅stackoverflow.com/a/3437484/2436175 也许错过的是一些关于这更安全的原因的解释。
  • 好像只有gcc,不是ISO C方案
【解决方案3】:

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

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

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

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

【讨论】:

  • 在 C++ 中,它应该是一个模板函数,适用于 any 类型。当然也不需要重写它; &lt;algorithm&gt; 中已有一个。
  • 您也可以在 C99 中编写内联函数,或者使用编译器扩展(MSVC 中的__inline,GNU C89 中的__inline__)。
【解决方案4】:

我觉得这个方法比较可爱:

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

【讨论】:

    【解决方案5】:

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

    数字浮点数时,我想添加一个解决方案。


    考虑数字是浮点数并且其中一个数字是not-a-number。那么a &lt; 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。它们都有相同的

    【讨论】:

    • 唯一提到NaN的答案,让我想到了这个问题
    【解决方案6】:

    如果我只是想稍微混淆一下,我可能会使用类似的东西:

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

    我认为 Doynax 的解决方案也很可爱。通常对宏参数被多次评估的保留意见。

    【讨论】:

      【解决方案7】:

      为了稍微混淆,试试这个:

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

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

      【讨论】:

      • 假设类型为 32 位。
      • 谢谢 - 这就是我要找的。​​span>
      • 遗憾的是,即使对于 32 位整数,这实际上也不起作用,除非您认为 2147483647 小于 -1。
      • @Stephen:你什么意思?在 2 的恭维中,它更小。 (-1 的最大值无符号)
      • @GMan:-1 无疑小于 2147483647,两者都是整数,并且在以任何宽度足以表示两者的有符号类型进行比较时(例如,32 位二进制补码整数)。无符号比较与问题无关。
      猜你喜欢
      • 1970-01-01
      • 2018-10-13
      • 1970-01-01
      • 2014-11-13
      • 1970-01-01
      • 1970-01-01
      • 2011-01-12
      • 1970-01-01
      • 2020-01-02
      相关资源
      最近更新 更多