【问题标题】:how to pass arguments to function and use these arguments in macro function inside it如何将参数传递给函数并在其中的宏函数中使用这些参数
【发布时间】:2018-01-31 10:45:21
【问题描述】:

我想做这样的事情

#define GREATER_THAN_ZERO(a) a>0? 1:0

在另一个类似的函数中使用这个宏

void test(int x)
{  if (GREATER_THAN_ZERO(x) == 1) printf("more than zero");
   else printf("less than zero");
}

但是当我使用测试功能时,它总是打印“小于零” 注意:这是一个例子,不是真实情况,但我想做类似的事情(在函数中使用宏) 任何人都可以帮助我吗? 编辑 我有这样的配置文件

 #define LED_u8_MODE_0          LED_u8_REVERSE
 #define LED_u8_MODE_1          LED_u8_NORMAL

在程序中我有一个宏函数

#define LED_u8_GET_MODE(LED_u8_INDX)        (LED_u8_INDX == 0)? LED_u8_MODE_0: \
(LED_u8_INDX == 1)? LED_u8_MODE_1: \
(LED_u8_INDX == 2)? LED_u8_MODE_2: \
(LED_u8_INDX == 3)? LED_u8_MODE_3: 800

然后我在这个函数中使用它

    void LED_voidSetLedOnWithIndx(u8 Copy_u8LedIndx)
{
    if(LED_u8_GET_MODE(Copy_u8LedIndx) == LED_u8_NORMAL)
    {
        DIO_voidSetPinValue(Copy_u8LedIndx, DIO_u8_HIGH);
    }
    else //if(LED_u8_GET_MODE(Copy_u8LedIndx) == LED_u8_REVERSE)
    {
        DIO_voidSetPinValue(Copy_u8LedIndx, DIO_u8_LOW);
    }
}

【问题讨论】:

  • 显示一个最小的代码示例,展示引用的问题,读者可以使用它来复制它。如果这不是你的真实案例,请给出一个并非完全愚蠢的真实案例。你引用的宏远比写thing > 0 糟糕得多,而且会激怒你的代码的读者。另外,为什么是? 1 : 0?你知道它已经返回了一个布尔值,对吧?
  • 显示一个最小的代码示例,展示引用的问题,读者可以使用它来复制它。目前,我们只有一个不完整的片段和您关于它导致问题的声明,没有证据表明问题行为是如何产生的。我们可以自己编写测试来证明或反驳您所说的,但这不是我们的工作。
  • 标准保证 C 中的比较运算符无论如何都返回 0 或 1,因此三元运算符毫无用处...
  • 安全宏应始终将参数放入括号中,整个宏也应如此,所以:GTZ(a) ((a)>0?1:0) 或简单地说(考虑我之前的评论!):GTZ(a) ((a)>0)
  • @AjayBrahmakshatriya 我不知道你在说什么。不需要== 1> 运算符已经返回了 01 的结果,它保证在任何布尔上下文中都能正确运行,并且我所见过的所有良好的编码风格都不鼓励明确比较布尔值的某些值。跨度>

标签: c c-preprocessor preprocessor


【解决方案1】:

我无法用您发布的代码重现问题,但您提到这不是真实情况,我确实知道问题所在。

表达式未按您的预期关联。展开后,表达式为:

x>0? 1:0 == 1

哪些分组为:

x>0? 1:(0 == 1)

相当于:

x>0? 1:0

这仍然按预期工作。但如果你有:

if (GREATER_THAN_ZERO(x) == 0)

那么你最终会得到:

x>0? 1:0 == 0

或:

x>0? 1:(0 == 0)

始终为 1。

宏定义存在两个基本问题:(1) 它没有保护其参数免于误关联,以及 (2) 它没有保护结果免于误关联。

正确的写法是:

#define GREATER_THAN_ZERO(a) ((a) > 0 ? 1 : 0)

(a) 周围的括号允许您将表达式作为参数传递,而不必担心它被重新关联。整个宏主体周围的括号允许您在表达式中使用宏而无需重新关联。

在这种特殊情况下,?: 运算符是多余的,因为n > 0 总是返回 0 或 1,因此您可以使用:

#define GREATER_THAN_ZERO(a) ((a) > 0)

结果相同。

同样,将结果与1 进行比较没有任何意义,并表明正在发生一些不寻常的事情。简单的写法更自然:

if (GREATER_THAN_ZERO(x))

这隐含地测试它是否非零。请记住,if (n) 等同于 if (n != 0)

【讨论】:

    【解决方案2】:

    评论太大,因此回答:我建议使用不同的格式(但括号已调整):

    #define LED_u8_GET_MODE(LED_u8_INDX)  \
        (                                 \
            (LED_u8_INDX) == 0            \
            ? (LED_u8_MODE_0)             \
            : (LED_u8_INDX) == 1          \
                ? (LED_u8_MODE_1)         \
                : (LED_u8_INDX) == 2      \
                    ? (LED_u8_MODE_2)     \
                    : (LED_u8_INDX) == 3  \
                        ? (LED_u8_MODE_3) \
                        : 800             \
        )
    

    或者你不同意这更容易阅读?

    尽管如此,许多三元运算符难以阅读和处理,我宁愿考虑将整个宏替换为内联函数:

    inline int ledGetMode(int index)
        // (if need be, adjust parameter and return value types appropriately)
    {
        switch(index)
        {
            case 0:
                return LED_u8_MODE_0;
            // ...
            default:
                return 800;
        }
    }
    

    看起来更简洁,并且作为内联应该不会对宏产生任何开销...

    不过,主要优点是您可以轻松跳过参数或结果关联不良以及对参数进行多次评估的任何麻烦!

    【讨论】:

      猜你喜欢
      • 2018-05-16
      • 2014-06-04
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-04
      • 1970-01-01
      • 2013-01-27
      相关资源
      最近更新 更多