shakim
shakim

Reputation: 186

Behavior of ## operator in nested call

I was reading a book on C programming language where I found:

#define cat(x,y) x##y
#define xcat(x,y) cat(x,y)

calling cat(cat(1,2),3) produces error whereas calling xcat(xcat(1,2),3) produces expected result 123.

How are both working differently ?

Upvotes: 5

Views: 185

Answers (1)

haccks
haccks

Reputation: 106112

Macros whose replacement lists depends on ## usually can't be called in nested fashion.
cat(cat(1,2),3) is not expanded in a normal fashion, with cat(1,2) yielding 12 and then cat(12, 3) yielding 123.
Macro parameters that are preceded or followed by ## in a replacement list aren't expanded at the time of substitution.

6.10.3.1 Argument substitution

1 After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.

As a result, cat(cat(1,2),3) expands to cat(1,2)3, which can't be expanded further, because there is no macro named cat(1,2)3.

In case

#define xcat(x,y) cat(x,y)  

writing xcat(xcat(1,2),3) will work. As the preprocessor expands the outer call of xcat, it will expand xcat(1,2) as well; the difference is that xcat's replacement list does not contain ## anymore.

xcat(xcat(1,2),3) ==> cat(12, 3) ==> 12##3 ==> 123

Upvotes: 5

Related Questions