Reputation: 135
I've been working on an embedded C project for a few days and I've found some interesting configuration files that use a lot of macros.
The code looks like this
// 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]))
I don't understand what really happens inside these //?????? //?????? "tags" in config.h. Also I am not sure if #if defined(CONFIG_PERIPH_0) is evaluated as TRUE or FALSE because before it, there is #define CONFIG_PERIPH_0(ch, interrupt)... After running preprocessing the generated arrays are these
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};
};
I wrote an example to highlight the difference between #define name and #define name(args) in terms of evaluating #ifdef name or #if defined(name) in both cases MACROS
Upvotes: 0
Views: 104
Reputation: 93486
Whether the macro takes arguments or not does not affect whether it is defined or not. The name alone is what you test for defined, the arguments are irrelevant because the macro is not expanded in the #ifdef / #if defined test.
Upvotes: 0
Reputation: 222933
The code in “config.h” appears designed for some earlier code to define CONFIG_PERIPH_0
or CONFIG_PERIPH_1
but not both.
If CONFIG_PERIPH_0
is defined, this code defines CONFIG_PERIPH_1
to be null—any use of CONFIG_PERIPH_1(…)
is replaced with nothing (an empty token list). Conversely, if CONFIG_PERIPH_1
is defined, this code defines CONFIG_PERIPH_0
to be null.
Then the code uses both CONFIG_PERIPH_0
and CONFIG_PERIPH_1
, knowing that the one that was defined by the earlier code will be replaced as defined and the other will have no effect.
Whether a macro is defined as object-like (#define foo replacement-tokens
) or function-like (#define foo(argument) replacement-tokens
) is irrelevant to the defined
operator or the #ifdef
directive. If the macro is defined either way, the defined
operator evaluates as true. If it is not defined, the operator evaluates as false.
Upvotes: 1