If I have:
#define X 5
#define Y X
what happens in the preprocessor for that kind of thing? Is it going through the whole file and changes every X to 5, then comes back up to the next define and then changes every Y to 5 (because in the previous iteration Y got 5) ?
The C standard has a special terminology for how macros are expanded.
Macro names are, in effect, stored in a big table of "all macros defined at this time". Each table entry "macro name" on the left (and any arguments in the middle) and "expansion token-stream" on the right.
When a macro is to be expanded (because it occurs in some non-preprocessor line, or in a position in a preprocessor line in which it must be expanded -- e.g., you can
#define STDIO <stdio.h>and then#include STDIO), the table entry is "painted blue", and then the replacement token-stream is read (with argument expansion as also dictated by the standard).If the replacement token-stream contains the original macro name, it no longer matches, because the "blue paint" covers up the name.
When the replacement token-stream has been fully handled, the "blue paint" is removed, re-exposing the name.
Thus:
adds
X: (no arguments),5to the table.Then:
adds:
Y: (no arguments),Xto the table.Somewhere later in the file, you might have an occurrence of the token
Y. Assuming neither of the above have been#undefed (removed from the table), the compiler must first "paint the table entry forYblue" and replace the tokenYwith the tokenX.Next, the compiler must "paint the table entry for
Xblue" and replace the tokenXwith the token5.The token
5is not a preprocessor macro name (it can't be by definition) so the token5passes beyond the reach of the preprocessing phase. Now the "blue paint" is removed from theXtable entry, as that's done; and then the "blue paint" is removed from theYentry, which is also done.If you were to write instead:
then the sequence, on encountering a later token
Y, would be:YblueY,Y,Y,theletteriscalledY!Yis painted blue those don't match, and,cannot match, so those are all passed on to the rest of the compiler;the,letter,is, andcalledmust be checked but are probably not in the table and hence passed on;Yis still painted blue so does not match and is passed on, and!cannot match and is passed on.