4.7 KiB
[cpp.concat]
15 Preprocessing directives [cpp]
15.7 Macro replacement [cpp.replace]
15.7.4 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.128
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.
[Note 1:
Concatenation can form a universal-character-name ([lex.charset]).
â end note]
If the result is not a valid preprocessing token, the program is ill-formed.
The resulting preprocessing token is available for further macro replacement.
The order of evaluation of## operators is unspecified.
[Example 1:
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') // this goes away== 0) str(: @\n), s);#include xstr(INCFILE(2).h) glue(HIGH, LOW);
xglue(HIGH, LOW) results inprintf("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 ## preprocessing tokens in the macro definition is optional.
â end example]
[Example 2:
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); // equivalent to char p[] = "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 preprocessing token, consisting of two adjacent sharp signs, but this new preprocessing token is not the## operator.
â end example]
[Example 3:
To illustrate the rules for placemarker preprocessing tokens, the sequence#define t(x,y,z) x ## y ## zint j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) }; results inint j[] = { 123, 45, 67, 89, 10, 11, 12, };
â end example]
Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within translation phase 4.