Array of macros in c -- is it possible

swamp_law picture swamp_law · Apr 8, 2016 · Viewed 7.5k times · Source

I was wondering if it is possible to create something like an array of macros. I've implemented the following code which works:

struct led_cmds_
{ 
    ioport_pin_t *commands[LED_COUNT] ; 
};
struct led_cmds_ the_led_cmd_ ; 

void populate() {
    the_led_cmd_.commands[0] = SPECIFICPIN(0);
}

and in main:

int main(void) 
{
    //.....  
    populate();
    LED_On(the_led_cmd_.commands[0]); 
}

SPECIFICPIN(x) is macro defined as:

#define SPECIFICPIN(X) (LED##X##_PIN) 

What I was hoping for is a way to is a way to do something like this:

#define ioport_pin_t* ARR_LED[LED_COUNT] \
for (int j = 0; j < LED_COUNT; j++) ARR_LED[j] = SPECIFICPIN(j);

and then only need to call the following when I want to use the specific pin

LED_On(ARR_LED[some_number])

when I try to do that I get an ARR_LED undeclared (first use in this function) error.

When I try to call SPECIFICPIN(x) where x is an int iterator in a for loop for example, I get an error saying something like 'LEDx_PIN' undeclared...

Answer

tofro picture tofro · Apr 8, 2016

You need to work on your terminology. An array of macros is not possible. Macros are no data type, but rather pure text replacement before your program is actually compiled.

I guess " populate an array using macros " is what you want to do. But it is not possible to do that in a compile-time loop - What you seem to want to achieve with your ioport_pin_t macro attempt. Macros do not have the capability to expand to more instances of text elements than you have initially given. There is no such feature as looping at compile time through macro expansions and do repetitive expansion of macros.

Your for loop loops at run-time, while the macro is being expanded at compile-time. Once you have made yourself aware what is done by the preprocessor what is done by the compiler, and what is done at run-time by the finished program, you will see that will not work.

Something like

#define P(X) {(LED##X##_PIN)}

ioport_pin_t *commands[LED_COUNT] = {
  P(0), P(1), P(2),......}

#undefine P

Would be the closest thing possible to what you seem to want. Note the main use of the pre-processor is not to save you typing effort - You would be better off using copy & paste in your editor, achieve the same thing and have clearer code.