【问题标题】:Function call as argument to C macro函数调用作为 C 宏的参数
【发布时间】:2015-07-12 19:51:02
【问题描述】:

首先是一个小代码:

int counter = 0;

int get_counter() { return counter++; }

#define EVEN_OR_ZERO(cc) ( (cc) % 2 == 0 ? (cc) : 0 )

int next_even_or_zero = EVEN_OR_ZERO(get_counter());

这段代码可能看起来不错,但是...让我们扩展宏:

int next_even_or_zero = get_counter() % 2 == 0 ? get_counter() : 0;

如您所见,宏只会返回奇数 - 这与预期(或期望)相反。

问题:有没有什么方法可以通过宏来完成这项工作?还是常规函数是唯一的方法?

//This works as wanted
int even_or_zero(int value) { return value % 2 == 0 ? value : 0; }

【问题讨论】:

  • 在 C++ 中还是在 C 中?您已经使用了这两个标签,因此很难知道您想要什么答案。
  • 至少在 C++ 中,像这样的宏函数不是一个好主意。
  • 答案很简单:除非有充分的理由,否则不要使用宏。这个案例不是其中之一。
  • 理解你为什么需要一个宏会很有帮助。它是否需要适用于int 以外的类型?我们可以假设参数可以复制或捕获吗?等等。
  • 你知道get_counter() 被调用了两次,不是吗?

标签: c++ c function macros arguments


【解决方案1】:
#define EVEN_OR_ZERO(cc) even_or_zero(cc)

这可能是一个完美的答案,也可能是一个糟糕的笑话,这取决于您为什么需要宏,而您没有告诉我们。

【讨论】:

    【解决方案2】:

    答案很简单:除非有充分的理由,否则不要使用宏。这个案例不是其中之一:

    int even_or_zero(int i) {
        if (i % 2) {
            return 0;
        } else {
            return i;
        }
    }
    

    【讨论】:

    • ... 内联函数是这里的门票(假设 c++)
    【解决方案3】:

    制作两个函数。

    int getCurrentCounter() { ... } // just return here
    int getNextCounter() { ... } // increment here
    

    这就是 PSQL 的工作方式 - 例如 - 序列。


    此外,这似乎是非常糟糕的代码设计。

    • 不要在 C++ 中使用宏,有更多更好的方法可以在不使用宏的情况下(通常)实现您的目标
    • 对全局变量有副作用的函数不是很好。想想用它的计数器创建结构/类并向它添加方法是否会更好。或者更好的是,可以将方法隐藏在 set 方法/类中作为他们的朋友来限制谁可以影响计数器。

    【讨论】:

      最近更新 更多