Files
cppdraft_translate/cppdraft/cpp/concat.md
2025-10-25 03:02:53 +03:00

4.7 KiB

[cpp.concat]

15 Preprocessing directives [cpp]

15.7 Macro replacement [cpp.replace]

15.7.4 The ## operator [cpp.concat]

1

#

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

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

3

#

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.

4

#

[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]

5

#

[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]

6

#

[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]

128)128)

Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within translation phase 4.