I'm experimenting to see how far I can abuse the C preprocessor and I have stumbled across an interesting problem.
I have the following macro defines:
#define if(x) if (x)
#define do {
#define elif(x) } else if (x) {
#define else } else {
#define done }
Which should allow me to write:
if (i == 1)
do
...
elif (i == 2)
...
else
...
done
And it works perfectly fine if I only use if
and else
, except the introduction of elif
is problematic because the macro expands as:
} } else { if (x) {
due to the else
being defined.
Is there any way I can get elif
to use 'raw' else
without having it picked up by the preprocessor? I think I need to try nesting multiple defines to trick the preprocessor into pasting the word directly without parsing it but I'm not sure how to achieve this.
Any ideas, or is this not possible in GCC?
Edit:
In essence, this can be boiled down to the following problem:
#define A B
#define B C
For the two given defines A
and B
, how can I get A
to still resolve to the literal word B
and not go through the second define and end up as C
?
Update
I think I managed to solve it. I utilized that:
is the same as
What we need from there is to save the result of
x
. We cannot reuse it, sincex
might be an expression with side effects. So:Now, we can check
b
to see if the above for loop was executed or not. A complete if-elif-else pattern done with for loops can look like this:With that, we can wrap it up like this, but be aware. However, this will not work well if you do a
if(x) break
inside a loop. See below.Demo: https://onlinegdb.com/Zq6Y7vm5Q
An alternative approach without
break
statements:Do note however, that both of these might fail if you have a
break
statement in them like this:Because that would expand to:
Note:
It should be obvious, but if you decide to use this code (don't) then use better names than
b
andc
to avoid collisions.Old workaround
Not quite what you asked for, but you have admitted that you're basically just abusing the preprocessor. :)
But an easy workaround is to use a synonym for
else
.Demo: https://onlinegdb.com/Cp-gYpOvm
It works with zero, one or multiple instances of elif, and regardless of how many elifs, it works with and without otherwise.