25

I found an interesting little blog post that explains how to generate (semi) unique names in a macro by using the line number:

// Do magic! Creates a unique name using the line number
#define LINE_NAME( prefix ) JOIN( prefix, __LINE__ )
#define JOIN( symbol1, symbol2 ) _DO_JOIN( symbol1, symbol2 )
#define _DO_JOIN( symbol1, symbol2 ) symbol1##symbol2

There are two things here that really confuse me:

  1. Why does the LINE_NAME macro even work if JOIN is declared after it in the file? I thought the C preprocessor did a linear pass, and thus would need the macros to be defined based on dependency, just like C functions need to be defined before they're used.
  2. Why is it necessary to use both the JOIN and _DO_JOIN macros in order to get the correct result? Having this level of indirection in the macros seems very strange.

I have a feeling that the answers to both those questions are related, and have to do with the way that the C preprocessor evaluates macros. (However, my intuition on how macros work is apparently way off since I didn't even think that the example was valid.)

DaoWen
  • 32,589
  • 6
  • 74
  • 101
  • Possible duplicate of [Why do I need double layer of indirection for macros?](http://stackoverflow.com/questions/8231966/why-do-i-need-double-layer-of-indirection-for-macros) โ€“ Antonio Apr 19 '17 at 13:55

1 Answers1

14

Why does the LINE_NAME macro even work if JOIN is declared after it in the file?

Macros are not functions, when you call them compiler expands them, and there compiler at the using point knows about all defined macros.

Why is it necessary to use both the JOIN and _DO_JOIN macros in order to get the correct result? Having this level of indirection in the macros seems very strange.

Because __LINE__ itself is a macro, it needs two level expanding.

Otherwise the output is not prefix1234 it will be prefix__LINE__.

it's useful to read this answer too, and this thread.

Community
  • 1
  • 1
masoud
  • 55,379
  • 16
  • 141
  • 208
  • OK, so the extra macro essentially just forces the preprocessor to do another find/replace pass over the resulting string. If the result of `JOIN(prefix, __LINE__)` also happened to be match a macro name, would that also get substituted? โ€“ DaoWen Oct 29 '13 at 18:29
  • 2
    @DaoWen: Yes. The exact rules are: if you have a macro definition `#define FOO(x, ...) ...`, then any argument `x` gets expanded recursively *unless it is the argument of the stringizing or token-pasting operator* (`#` and `##`). See C99 ยง6.10.3.1/1. โ€“ Adam Rosenfield Oct 29 '13 at 18:48