[cpp.concat] # 15 Preprocessing directives [[cpp]](./#cpp) ## 15.7 Macro replacement [[cpp.replace]](cpp.replace#cpp.concat) ### 15.7.4 The ## operator [cpp.concat] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1847) A## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition[.](#1.sentence-1) [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1854) 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[.](#2.sentence-1)[128](#footnote-128 "Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within translation phase 4.") [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1866) 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[.](#3.sentence-1) 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[.](#3.sentence-2) [*Note [1](#note-1)*: Concatenation can form a [*universal-character-name*](lex.universal.char#nt:universal-character-name "5.3.2 Universal character names [lex.universal.char]") ([[lex.charset]](lex.charset "5.3.1 Character sets"))[.](#3.sentence-3) — *end note*] If the result is not a valid preprocessing token, the program is ill-formed[.](#3.sentence-4) The resulting preprocessing token is available for further macro replacement[.](#3.sentence-5) The order of evaluation of## operators is unspecified[.](#3.sentence-6) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1890) [*Example [1](#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[.](#4.sentence-2) — *end example*] [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1932) [*Example [2](#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[.](#5.sentence-3) — *end example*] [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1957) [*Example [3](#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)](#footnote-128)[128)](#footnoteref-128) Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within translation phase 4[.](#footnote-128.sentence-1)