Nested ## Statement in C Preprocessor

Case 1)

#define CONCATENATE(x,y) x##y

      

CONCATENATE (a, CONCATENATE (b, c)) gives aCONCATENATE (b, c).

Case 2)

 #define CONCATENATE(x,y) x##y
 #define CONCATENATE2(x,y) CONCATENATE(x,y)

      

CONCATENATE2 (a, CONCATENATE2 (b, c)) gives abc.

Why doesn't case 1 work? And what does case 2 do?
Please explain step by step the procedure.

+3


source to share


2 answers


The GCC docs explain it this way:

Macro arguments are fully expanded by macros before they are replaced in a macro object, unless they are collapsed or inserted with other tokens.

(in italics)

Operands of the ## (token in pasting) operator, on the other hand, will not be macro expanded and then pasted together. So considering

CONCATENATE(a,CONCATENATE(b,c))

      

the preprocessor does not expand CONCATENATE(b,c)

to expand the outer body of the macro, because it is the ## operand. The preprocessor instead splices the marker before rescanning to expand macros, so

a ## CONCATENATE(b,c)

      

becomes



aCONCATENATE(b,c)

      

before rescanning, and there is no aCONCATENATE macro (but if it did, it would be expanded).

On the other hand, for

CONCATENATE2(a,CONCATENATE2(b,c)),

      

the argument is CONCATENATE2(b,c)

not an operand of the ## (or #) operator, so it expands before being replaced into the body of the macro, which ultimately gives

CONCATENATE(a, bc)

      

as the first extension of an external macro. This is re-scanned for further extensions, which gives

abc

      

+2


source


When macros are used in a self-referential manner (or circular), as for CONCATENATE

, they do not expand recursively. That's why:

CONCATENATE(a,CONCATENATE(b,c))

gives aCONCATENATE(b,c)

.

In the second case, decomposition CONCATENATE2

is performed after processing CONCATENATE

. Hence, you get the right result.

Self-referential use of macros works great in most cases. The exceptions are token insertion and screening.

For example, if you have:

#define #define foo(x) int x

      

then

foo(foo(x));

      

expands to:

int int x;

      



If you have:

#define STR(y) #y

      

then

STR(STR(abcd));

      

expands to:

"STR(abcd)";

      

More details:

https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html

https://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification

How does the C preprocessor handle circular dependencies?

+2


source







All Articles