如何将参数传递给函数并在其中的宏函数中使用这些参数

时间:2018-01-31 10:45:21

标签: c c-preprocessor preprocessor

我想做那样的事情

#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);
    }
}

2 个答案:

答案 0 :(得分:6)

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

表达式未按预期关联。展开时,表达式为:

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)

答案 1 :(得分:0)

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

#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;
    }
}

看起来更干净,并且应该像内联一样,没有任何开销超过宏...

但主要的优点是,您只需跳过参数或结果不良关联以及参数多重评估的任何问题!