[cpp.concat] (original) (raw)

15 Preprocessing directives [cpp]

15.6 Macro replacement [cpp.replace]

15.6.3 The ## operator [cpp.concat]

A##preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.

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; however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.148

For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a##preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.

Placemarker preprocessing tokens are handled specially: concatenation of two placemarkers results in a single placemarker preprocessing token, and concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.

If the result is not a valid preprocessing token, the behavior is undefined.

The resulting token is available for further macro replacement.

The order of evaluation of##operators is unspecified.

[ Example

:

The sequence

#define str(s) # s #define xstr(s) str(s) #define debug(s, t) printf("x" # s "= %d, x" # t "= %s",
x ## s, x ## t) #define INCFILE(n) vers ## n #define glue(a, b) a ## b #define xglue(a, b) glue(a, b) #define HIGHLOW "hello" #define LOW LOW ", world"

debug(1, 2); fputs(str(strncmp("abc\0d", "abc", '\4')
== 0) str(: @\n), s); #include xstr(INCFILE(2).h) glue(HIGH, LOW); xglue(HIGH, LOW)

results in

printf("x" "1" "= %d, x" "2" "= %s", x1, x2); fputs("strncmp("abc\0d", "abc", '\4') == 0" ": @\n", s); #include "vers2.h" (after macro replacement, before file access) "hello"; "hello" ", world"

or, after concatenation of the character string literals,

printf("x1= %d, x2= %s", x1, x2); fputs("strncmp("abc\0d", "abc", '\4') == 0: @\n", s); #include "vers2.h" (after macro replacement, before file access) "hello"; "hello, world"

Space around the # and ## tokens in the macro definition is optional.

end example

]

[ Example

:

In the following fragment:

#define hash_hash # ## # #define mkstr(a) # a #define in_between(a) mkstr(a) #define join(c, d) in_between(c hash_hash d) char p[] = join(x, y);

The expansion produces, at various stages:

join(x, y) in_between(x hash_hash y) in_between(x ## y) mkstr(x ## y) "x ## y"

In other words, expanding hash_­hash produces a new token, consisting of two adjacent sharp signs, but this new token is not the## operator.

end example

]

[ Example

:

To illustrate the rules for placemarker preprocessing tokens, the sequence

#define t(x,y,z) x ## y ## z int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };

results in

int j[] = { 123, 45, 67, 89, 10, 11, 12, };

end example

]