【发布时间】:2020-11-10 16:00:31
【问题描述】:
我在嵌入式 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, interrupt)... 运行预处理后生成的数组是这些
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
【问题讨论】:
-
#ifdef和#if defined之间的唯一区别是#ifdef需要的字母更少。 -
@ThomasMatthews:对于拥有
#if defined X && Y == 3并将其更改为#ifdef X && Y == 3的人来说,这将是一个惊喜。 -
#ifdef预处理器指令测试符号(宏)是否已定义(或已存在)。它不测试符号的值。 -
@ThomasMatthews 在简单的情况下是正确的,但 ANSI C(又名 C89)引入的
#if defined语法允许更复杂的测试,例如:#if (defined XX || defined YY) && !defined ZZ。 -
看起来是如何编写英国媒体报道软件的完美示例。在初始化列表中间使用包含是简单的可怕设计。更好的设计可能是创建两个或多个结构初始化器列表,然后根据 #ifdef 使用结构的相关初始化器列表。 KISS 原则。