4
votes
#define LED1_ON() { /* twiddle port bit */ }
#define LED2_ON() { /* twiddle port bit */ }
//  ...
#define LED9_ON() { /* twiddle port bit */ }

#define LED_ON(x) LED##x_ON()

I would like to use the above code (or something similar) to have (for example) LED_ON(1) call macro LED1_ON(), or LED_ON(2) call macro LED2_ON().

I believe it is possible to make cpp do this, but clearly I don't have the syntax correct. Does anyone know the syntax to make this possible?

On the line where I call the LED_ON(2), gcc gives the error message:

undefined reference to `LEDx_ON'
3
I'm fairly sure you can't do this. The preprocessor only does one single pass. Maybe you could do something wild with synthesizing include filenames, but I'm not sure it'd be worth it. - Kerrek SB
I removed the "cpp" from your title. Many people (unfortunately) use that term to refer to C++, so it could be confusing. - Keith Thompson
I don't think there's much point in doing this. There may be a way to make it work, but even if so you'll still only be able to write LED_ON(3) rather than LED3_ON(); nothing other than a literal 3 would work. On the other hand, an inline function (or even a non-inline function) could easily use a switch statement that invokes the proper lower-level macro. - Keith Thompson
You'd do much better to reverse the operations. Write a general LED_ON(n) and redefine #define LED1_ON() LED_ON(1), etc. - Jonathan Leffler
What's the difference between the macro bodies? Without seeing that part, and assuming they're treated similarly, the obvious suggestion would be to just define a list of port constants, not to define whole separate macros for each one. - Leushenko

3 Answers

16
votes

You need to define LED_ON as

#define LED_ON(x)  LED##x##_ON()

you want to take the argument x and paste on an LED prefix and a _ON suffix.

0
votes

I think that the preprocessor mechanism shouldn't be overused. If some more serious logic starts to appear in the macros, maybe it's time to switch to inline functions? They are more readable, just as fast, more powerful and you have some help from the compiler in case of parameter types aso..

If you insist on #define LED_ON(x) macro and subsequent LEDs are controlled by subsequent bits of one port, you can try something like this:

#define LED_ON(x)   SetBit(port, 1<<x);
0
votes

Do something like this

#define LED_ON(num) \
    void LED_ON##num() \
    {\
        printf("set the bit for %d\n", num); \
    }\

LED_ON(1) 
LED_ON(2)

int main() {
    LED_ON1();
    LED_ON2();
}

LED_ON(1) and LED_ON(2) will be expanded to full function with name LED_ON1() and LED_ON2() And call functions as LED_ON1() LED_ON2()