使用__VA_ARGS __

时间:2019-01-30 04:08:27

标签: c++ c

考虑以下代码:

// Macros to support option testing
#define _CAT(a, ...) a ## __VA_ARGS__
#define SWITCH_ENABLED_false 0
#define SWITCH_ENABLED_true  1
#define SWITCH_ENABLED_0     0
#define SWITCH_ENABLED_1     1
#define SWITCH_ENABLED_      1
#define ENABLED(b) _CAT(SWITCH_ENABLED_, b)

我从3Dprinter固件Marlin复制而来,我不知道它如何支持opthin测试。在马林鱼中的用法如下:

#if ENABLED(USE_WATCHDOG)
  #include "watchdog.h"
#endif

很明显,此MACRO(已启用)(USE_WATCHDOG)的功能是确定是否定义了USE_WATCHDOG。   例如,我确实定义了USE_WATCHDOG,将其替换为ENABLED(b),扩展名为_CAT(SWITCH_ENABLED_,USE_WATCHDOG)。 _CAT会将SWITCH_ENABLED_,USE_WATCHDOG缝合到 SWITCH_ENABLED_USE_WATCHDOG,但是此宏不存在。为什么SWITCH_ENABLED_USE_WATCHDOG等于1,并最终包含“ watchdog.h”?

2 个答案:

答案 0 :(得分:0)

请注意,这些都是启用开关的默认设置:

#define SWITCH_ENABLED_true  1
#define SWITCH_ENABLED_1     1
#define SWITCH_ENABLED_      1

是的,如果不存在任何开关宏或替代,则最后一个将启用开关。

因此,您可以通过以下方式启用USE_WATCHDOG

  1. 覆盖USE_WATCHDOG(扩展为ENABLED(true)

    #define USE_WATCHDOG true
    
  2. 覆盖USE_WATCHDOG(扩展为ENABLED(1)

    #define USE_WATCHDOG 1
    
  3. 仅启用开关

    #undef USE_WATCHDOG
    #define SWITCH_ENABLED_USE_WATCHDOG 1
    
  4. 没有定义

    #undef USE_WATCHDOG
    #undef SWITCH_ENABLED_USE_WATCHDOG
    

如果这些都不适合您,则可能其中一个是在您不知道的标头中定义的,或者是在代码之外(例如,项目设置,Makefile等,或预先包含的文件)定义的

答案 1 :(得分:0)

  

此宏的功能显然是ENABLED(USE_WATCHDOG),用于确定是否定义了USE_WATCHDOG。

不完全是。目的是确定是否将其一方面定义为1true 或什么都没有定义,还是将其定义为0false,或者没有定义。另一方面。如果没有其他值的其他支持(未显示),则必须定义该值,否则该值必须是其中的一个值才能成功编译。

  

例如,我确实定义了USE_WATCHDOG,我将其替换为ENABLED(b),扩展名为_CAT(SWITCH_ENABLED_,USE_WATCHDOG)。

除了用作###预处理运算符的操作数外,宏的参数在被替换为宏的替换文本之前已完全展开。因此,ENABLED(USE_WATCHDOG)的扩展取决于USE_WATCHDOG的定义(如果有)。例如,如果将其定义为true

#define USE_WATCHDOG true

然后ENABLED(USE_WATCHDOG)扩展为

_CAT(SWITCH_ENABLED_, true)

,然后对其进行重新扫描以查找其他宏替换。

  

_CAT会将SWITCH_ENABLED_,USE_WATCHDOG缝合到SWITCH_ENABLED_USE_WATCHDOG中,但是该宏不存在。

您已经在这里摆脱了束缚。在USE_WATCHDOG定义如上的情况下,实际上发生的是,在这个阶段_CAT(SWITCH_ENABLED_, true)被扩展到

SWITCH_ENABLED_true

(即使true本身被定义为宏),也将再次对其进行重新扫描以查找其他宏替换。 最后又进行了一轮宏替换,将其简化为

1
  

为什么SWITCH_ENABLED_USE_WATCHDOG等于1,并最终包含“ watchdog.h”?

在所提供的代码中不是,但这并不重要(请参见上文)。

尤其要注意,_CAT宏对于完成所有这些工作至关重要。您需要双层宏扩展,才能在将结果粘贴到USE_WATCHDOG之前扩展SWITCH_ENABLED_,这似乎是您的误解。