4

I have difficulty understanding how rewriting rules are applied by the C preprocessor in the following context. I have the following macros:

#define _A(x) "A" _##x
#define _B(x) "B" _##x
#define X(x) _##x

The idea is that each of these macros uses the concatenation to create a new expression, which can itself be a macro — if its a macro, I'd like it to be expanded:

Now, the following expands just like I expect:

X(x)       expands to _x
X(A(x))    expands to "A" _x
X(A(B(x))) expands to "A" "B" _x

However, once the same macro is used more then once, the expansion stops:

X(A(A(x)))       expands to "A" _A(x), expected "A" "A" _x
X(B(B(x)))       expands to "B" _B(x), expected "B" "B" _x
X(A(B(A(x))))    expands to "A" "B" _A(x), expected "A" "B" "A" _x 
X(A(B(A(B(x))))) expands to "A" "B" _A(B(x)), expected "A" "B" "A" "B" _x 

I guess that there is some sort of "can expand same-named macro only once" rule at play here? Is there something I can do to get the macros to expand the way I want?

MrMobster
  • 1,851
  • 16
  • 25
  • 2
    This is because you use the `##` operator, which does not evaluate macros; this is a duplicate of [Nested macro expansion](https://stackoverflow.com/questions/31610231/nested-macro-expansion) – underscore_d Jul 28 '17 at 13:55
  • 2
    or [How to evaluate a nested preprocessor macro](https://stackoverflow.com/questions/13074432/how-to-evaluate-a-nested-preprocessor-macro) – underscore_d Jul 28 '17 at 13:55
  • Maybe my brain is not working right, but I don't see how this is a duplicate of those questions. In the questions you linked, the problem was to expand the macro first and concatenate later. I want to do exactly the opposite: concatenate first and then expand. Also, at least some expansion is happening or the examples I posted won't expand at all (e.g. we'd get X(A(x)) - _A(x), but _A(x) clearly gets expanded) – MrMobster Jul 28 '17 at 14:02
  • 1
    I think your root problem here is that the macro preprocessor is fairly simple in the processing it does as a kind of one pass parse and output.What you are wanting to do is really a different operator than what the `##` operator does. It sounds like you want an operator to tell the preprocessor to generate a symbol using the `##` operator and to then loop back and reevaluate the symbol to see if there is any other operations that need to be done with this new symbol. That's now how the preprocessor works. – Richard Chambers Jul 28 '17 at 14:11
  • @RichardChambers but how do you then explain that X(A(x)) gets expanded correctly? Indirection using concatenation to a new macro is a well known technique and works reliably, because the preprocessor does a rescan after the first expansion. My question is about why this process seems to stop if I use the same macro name more then once. – MrMobster Jul 28 '17 at 14:19
  • 1
    @MrMobster if `A` and `B` were themselves macros, and you didn't use `##` to build the names, then you get recursion indefinitely. That's because the corresponding expansions are done during *argument substitution* phase, which fully expands all macro arguments before putting them into the replacement list. a.s. is not subject to "blue paint" (aka, 6.10.3.4p2, see Toby's answer); it's a different scan. *Rescan and further replacement* happens afterwards; _is_ subject to 6.10.3.4 (since that's what this is doing), and does _not_ support recursion of the same macro. – H Walters Jul 28 '17 at 14:54

2 Answers2

5

When I want to work out macro expansion I generally use this diagram, which I constructed using section 6.10.3 from standard. Hope it helps...

enter image description here

As Toby has already mentioned, nested macros will not be expanded recursively.

Jimbo
  • 4,352
  • 3
  • 27
  • 44
  • Thanks, this is super useful! – MrMobster Jul 28 '17 at 14:51
  • ...but wrong. Following the yes-no-no path for decisions, the block says "If nested replacements encounter name of macro being replaced, it is not replaced to avoid recursion". That refers to blue paint; but blue paint applies during rescan and further replacement (6.10.3.4); and that block is describing argument substitution (6.10.3.1) which imposes no such restriction. – H Walters Jul 28 '17 at 15:23
  • Oops. I'll have to check that out! Deleting answer in mean time – Jimbo Jul 29 '17 at 19:45
  • @H Walters: I stand corrected, thanks for pointing that out :) – Jimbo Aug 07 '17 at 11:09
3

C99 draft says that there's no recursion permitted in macro expansion:

6.10.3.4 Rescanning and further replacement

  1. After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed. The resulting preprocessing token sequence is then rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.
  2. If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

So X(A(A(x))) expands to "A" _A(x), but that expansion is not itself expanded, as you've seen.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103