代码部分作为宏参数

时间:2017-05-19 07:15:50

标签: c c-preprocessor

出于调试目的,我定义了以下宏

#define SECTION_TIME(out, s) GPIO_SetOut(out); \
                             s \
                             GPIO_ClrOut(out);

用法:

SECTION_TIME(GPIO_fooOut,
      foo();
      bar();
      foo=bar^foo;....;....;
)

目标:需要确定一些代码的时间。 有时这个宏不编译。我错过了解某事吗? PS:我也尝试用{}

包围我的代码
error: macro "SECTION_TIME" passed 6 arguments, but takes just 2

3 个答案:

答案 0 :(得分:2)

当代码像鸭子一样走路并像鸭子一样说话时,它的表现就像鸭子一样。我的意思是SECTION_TIME(GPIO_fooOut, ...)(有点)看起来像一个陈述,而实际上它映射到3个或更多的陈述。这很糟糕,你应该努力使它成为一个陈述。

这实际上并不困难,用于此的常用习惯是将宏内容包装在do { ... } while (0) 中,而不用一个尾随分号(以便将尾随分号提供给结尾)宏调用。)

所以你至少应该将你的宏改为

#define SECTION_TIME(out, s) \
do { \
        GPIO_SetOut(out); \
        s; \
        GPIO_ClrOut(out); \
} while (0)

另请注意,您应该在宏中放置s的终止分号而不是参数。因此应该像

一样调用宏
SECTION_TIME(GPIO_fooOut,
      foo();
      bar();
      foo=bar^foo;....;....
);

根据使用情况,使用SETION_TIME_BEGIN和SECTION_TIME_END的建议可能是更好的解决方案。

答案 1 :(得分:0)

使用可变参数宏解决

#define BOARD_SECTION_TIME(out, ...)    do {              \
                                        GPIO_SetOut(out); \
                                        __VA_ARGS__       \
                                        GPIO_ClrOut(out); \
                                        } while(0)

答案 2 :(得分:0)

我也使用__VA_ARGS__的方式,但我也通过定义第二个宏来制作一些类似咖喱的语法,该名称位于第一个宏中:

#define SECTION_TIME(out) \
    do { \
        /* remember to save the value, so that the same output is always cleared and can be used in the second one */ \
        decltype(out) _o = out; \
        GPIO_SetOut(_o); \
        SECTION_TIME_BLOCK1
#define SECTION_TIME_BLOCK1(...) \
        {__VA_ARGS__}; \
        GPIO_ClrOut(_o); \
    } while(0);

它可以像这样使用:

SECTION_TIME(GPIO_fooOut) (
    foo();
    bar();
    foo=bar^foo;
    //....;....;
);

您会看到out输入参数是一个单独的元组,并且语法类似于if的语法,例如,只有括号不同。如果你只想定义一个宏,你可以说代码参数应该是一个元组:

// this macro is only a help to remove the brackets and can be used in multiple definitions

#define PP_REMOVE_BRACKETS(...) __VA_ARGS__

/**
 *  \param code a tuple containing the code you want to run
**/
#define SECTION_TIME(out, code) \
    do { \
        /* remember to save the value, so that the same output is always cleared */ \
        decltype(out) _o = out; \
        GPIO_SetOut(_o); \
        {PP_REMOVE_BRACKETS code}; \
        GPIO_ClrOut(_o); \
    } while(0);

可以这样使用:

SECTION_TIME(GPIO_fooOut, (
    foo();
    bar();
    foo=bar^foo;
    //....;....;
));