f78 Separate Expansion of Macro Arguments Contents|Index|Previous|Next
 

Separate expansion of macro arguments 

We have explained that the expansion of a macro, including the substituted actual arguments, is scanned over again for macro calls to be expanded.

What really happens is more subtle: first each actual argument text is scanned separately for macro calls. Then the results of this are substituted into the macro body to produce the macro expansion, and the macro expansion is scanned again for macros to expand. The result is that the actual arguments are scanned twice to expand macro calls in them.

Most of the time, this has no effect. If the actual argument contained any macro calls, they are expanded during the first scan. The result therefore contains no macro calls, so the second scan does not change it.

If the actual argument were substituted as given, with no pre-scan, the single remaining scan would find the same macro calls and produce the same results. You might expect the double scan to change the results when a self-referential macro is used in an actual argument of another macro (see Self-referential macros). The self-referential macro would be expanded once in the first scan, and a second time in the second scan. But this is not what happens. The self-references that do not expand in the first scan are marked so that they will not expand in the second scan either.

The pre-scan is not done when an argument is stringified or concatenated. Use the following input as an example.

This, then, expands to "foo". Once more, prescan has been prevented from having any noticeable effect. More precisely, stringification and concatenation use the argument as written, in un-prescanned form. The same actual argument would be used in pre-scanned form if it is substituted elsewhere without stringification or concatenation. This, then, expands to "foo" lose(4).

You might now ask, “Why mention the pre-scan, if it makes no difference? And why not skip it and make the preprocessor faster?” The answer is that the pre-scan does make a difference in three special cases:

We say that nested calls to a macro occur when a macro’s actual argument contains a call to that very macro. For example, if f is a macro that expects one argument, f (f (1)) is a nested pair of calls to f. The desired expansion is made by expanding f (1) and substituting that into the definition of f. The pre-scan causes the expected result to happen. Without the prescan, f (1) itself would be substituted as an actual argument, and the inner use of f would appear during the main scan as an indirect self-reference and would not be expanded. Here, the pre-scan cancels an undesirable side effect (in the medical, not computational, sense of the term) of the special rule for self-referential macros. We would like bar(foo) to turn into (1 + (foo)), which would then turn into (1 + (a,b)). But instead, bar(foo) expands into lose(a,b), and you get an error because lose requires a single argument. In this case, the problem is easily solved by the same parentheses that ought to be used to prevent mis-nesting of arithmetic operations. The problem is more serious when the operands of the macro are not expressions; for example, when they are statements. Then parentheses are unacceptable because they would make for invalid C code. In GNU C you can shield the commas using the ({. . .}) construct which turns a compound statement into an expression like the following. Or you can rewrite the macro definition to avoid such commas, using the following input. There is also one case where pre-scan is useful. It is possible to use pre-scan to expand an argument and then stringify it—if you use two levels of macros. Let’s add a new macro, xstr, to the previous definition. This expands into "4", not "foo". The reason for the difference is that the argument of xstr is expanded at pre-scan (because xstr does not specify stringification or concatenation of the argument). The result of pre-scan then forms the actual argument for str. str uses its argument without pre-scan because it performs stringification; but it cannot prevent or undo the pre-scanning already done by xstr. 0