#define name 和 #define name(arguments) 在 C 中涉及 #ifdef name 或 #if defined(name) 时有什么区别?

What is the difference between #define name and #define name(arguments) when it comes to #ifdef name or #if defined(name) in C?

我已经在一个嵌入式 C 项目上工作了几天,我发现了一些使用大量宏的有趣配置文件。

代码如下所示

// config.h   
//????? 
#if defined(CONFIG_PERIPH_0)
#define CONFIG_PERIPH_1(ch, interrupt)
#elif defined(CONFIG_PERIPH_1)
#define CONFIG_PERIPH_0(ch, interrupt)
#endif
 
       CONFIG_PERIPH_0(PERIPH_INPUTCHAN_28, FALSE)
       CONFIG_PERIPH_0(PERIPH_INPUTCHAN_27, FALSE)
       CONFIG_PERIPH_1(PERIPH_INPUTCHAN_29, TRUE)
       CONFIG_PERIPH_1(PERIPH_INPUTCHAN_30, FALSE)
//?????
#undef CONFIG_PERIPH_0
#undef CONFIG_PERIPH_1

// periph.h
#include "config.h"
#define CONFIG_PERIPH_0(ch, interrupt) { \
    .interruptEnable = interrupt, \
    .channel = ch \
},
periph_chan_config_t const PERIPH0_Array_Chs[] = {
    #include "config.h"  // the contents of "config.h" file is copied here
    {FALSE, 0};
};

#define CONFIG_PERIPH_1(ch, interrupt) { \
    .interruptEnable = interrupt, \
    .channel = ch \
},
periph_chan_config_t const PERIPH1_Array_Chs[] = {
    #include "config.h"  // the contents of "config.h" file is copied here
   {FALSE, 0};
};

#define SIZE_PERIPH0_ARRAY (sizeof(PERIPH0_Array_Chs)/sizeof(PERIPH0_Array_Chs[0]))
#define SIZE_PERIPH1_ARRAY (sizeof(PERIPH1_Array_Chs)/sizeof(PERIPH1_Array_Chs[0]))

我不明白这些里面究竟发生了什么//?????? //?????? config.h 中的“标签”。 另外我不确定 #if defined(CONFIG_PERIPH_0) 是否被评估为 TRUE 或 FALSE 因为在它之前,有 #define CONFIG_PERIPH_0 (ch, 中断)... 运行 预处理后生成的数组是这些

 periph_chan_config_t const PERIPH0_Array_Chs[] = {
      { .interruptEnable = 0u, .channel = PERIPH0_INPUTCHAN_28 },
      { .interruptEnable = 0u, .channel = PERIPH0_INPUTCHAN_27 },
      {0u, 0};
 };
 periph_chan_config_t const PERIPH1_Array_Chs[] = {
      { .interruptEnable = 1u, .channel = PERIPH1_INPUTCHAN_29 },
      { .interruptEnable = 0u, .channel = PERIPH1_INPUTCHAN_30 },
      {0u, 0};
 };

我写了一个例子来强调 #define name#define name(args) 在评估 #ifdef name#if defined(name) 在这两种情况下 MACROS

“config.h”中的代码似乎是为某些早期代码设计的,用于定义 CONFIG_PERIPH_0CONFIG_PERIPH_1,但不能同时定义两者。

如果定义了 CONFIG_PERIPH_0,则此代码将 CONFIG_PERIPH_1 定义为空——任何对 CONFIG_PERIPH_1(…) 的使用都将被替换为空(一个空标记列表)。相反,如果定义了 CONFIG_PERIPH_1,则此代码将 CONFIG_PERIPH_0 定义为 null。

那么代码中同时使用了CONFIG_PERIPH_0CONFIG_PERIPH_1,知道前面代码定义的那个会被替换成定义的,另一个就没有效果了。

宏定义为类对象 (#define foo replacement-tokens) 还是类函数 (#define foo(argument) replacement-tokens) 与 defined 运算符或 #ifdef 指令无关.如果以任一方式定义宏,则 defined 运算符的计算结果为真。如果未定义,则运算符计算为 false。

宏是否带参数不影响它是否被定义。名称本身就是您为 defined 测试的内容,参数无关紧要,因为宏未在 #ifdef / #if defined 测试中扩展。