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

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

Answers (2)

Clifford
Clifford

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

Eric Postpischil
Eric Postpischil

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

Related Questions