user2799508
user2799508

Reputation: 848

Token pasting in C not clear

#include <stdio.h>

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

int main(void)
{
   int token34 = 40;

   tokenpaster(34);
   return 0;
}

The output is:

token34 = 40

The author says that:

How it happened, because this example results in the following actual output from the preprocessor:

printf ("token34 = %d", token34);

How token##n is being converted into token34? Should it not be token#34?

Upvotes: 1

Views: 191

Answers (2)

vgru
vgru

Reputation: 51214

A single hash prefix (#) forces the preprocessor to stringify your argument. Double hash prefix (##) simply pastes the argument and merges it with its prefix.

This means that tokenpaster(34) will be expanded to:

printf ("token" "34" " = %d", token34)
                ^^^^               ^^
                  |                 |
                  |                 +---- pasted and merged
                  |
                  +---- enclosed in quotes

These three string literal parts are then merged into a single literal:

printf ("token34 = %d", token34)

According to the standard:

§6.10.3.2 The # operator

2 If, in the replacement list, a parameter is immediately preceded by a # preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument. (...)

and

§6.10.3.3 The ## operator

2 If, in the replacement list of a function-like macro, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence (...)

Upvotes: 0

Kninnug
Kninnug

Reputation: 8053

The double-hash in a preprocessor statement glues the two arguments together. So token##n becomes token##34 becomes token34. A single hash stringifies its argument. So #n becomes "34". And thus the whole macro-expansion is as follows:

tokenparser(34);
->
printf ("token" #n " = %d", token##n);
->
printf ("token" "34" " = %d", token##34);
->
printf ("token" "34" " = %d", token34);

and the compiler catenates the format string, so the end-result is:

printf ("token34 = %d", token34);

Upvotes: 2

Related Questions