考虑以下代码:
// 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”?
答案 0 :(得分:0)
请注意,这些都是启用开关的默认设置:
#define SWITCH_ENABLED_true 1
#define SWITCH_ENABLED_1 1
#define SWITCH_ENABLED_ 1
是的,如果不存在任何开关宏或替代,则最后一个将启用开关。
因此,您可以通过以下方式启用USE_WATCHDOG
:
覆盖USE_WATCHDOG
(扩展为ENABLED(true)
)
#define USE_WATCHDOG true
覆盖USE_WATCHDOG
(扩展为ENABLED(1)
)
#define USE_WATCHDOG 1
仅启用开关
#undef USE_WATCHDOG
#define SWITCH_ENABLED_USE_WATCHDOG 1
没有定义
#undef USE_WATCHDOG
#undef SWITCH_ENABLED_USE_WATCHDOG
如果这些都不适合您,则可能其中一个是在您不知道的标头中定义的,或者是在代码之外(例如,项目设置,Makefile等,或预先包含的文件)定义的
答案 1 :(得分:0)
此宏的功能显然是ENABLED(USE_WATCHDOG),用于确定是否定义了USE_WATCHDOG。
不完全是。目的是确定是否将其一方面定义为1
或true
或什么都没有定义,还是将其定义为0
或false
,或者没有定义。另一方面。如果没有其他值的其他支持(未显示),则必须定义该值,否则该值必须是其中的一个值才能成功编译。
例如,我确实定义了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_
,这似乎是您的误解。