## preprocessing tokens in a macro definitionAuthors: Jay Ghiron
Date: 2026-11-12
Submitted against: C23
Status: Open
Cross-references: 0017.22
Consider the following:
#define F(X)+X####X+
F()
What does this expand to? Specifically, this will do concatenation
with a placemarker preprocessing token and a ## preprocessing token.
So depending upon which ## gets evaluated first it will be
+##<placemarker>+ or +<placemarker>##+ after the first
concatenation. Since the remaining ## preprocessing token was in
the replacement list, should this do concatenation again? In either
evaluation order the two possible interpretations are the same. If
concatenation happens again, the result is two + preprocessing
tokens. If concatenation does not happen again, the result is a +
preprocessing token, then a ## preprocessing token, and then a +
preprocessing token. GCC, Clang, EDG, and TCC all agree that this
should do concatenation again, MSVC crashes when attempting to
preprocess this macro with its new preprocessor. See also DR 17
question twenty two, that was answered as two
concatenated # preprocessing tokens not doing concatenation after
becoming a ## preprocessing token. If there are no surrounding
preprocessing tokens, the behavior is unclear if concatenation does
happen again:
#define G(X)X####X
G()
GCC, Clang, EDG, and TCC all agree that this should expand to nothing,
MSVC crashes when attempting to preprocess this macro with its new
preprocessor. Though to reach the interpretation that this expands to
nothing, after the first concatenation the <placemarker>## or
##<placemarker> needs to do concatenation somehow despite one of the
preprocessing tokens to concatenate not being present. In the
following slightly different scenario there is disagreement among
compilers:
#define H(X)+X####+
int main(){
int x=0;
H()x;
return x;
}
This is invalid if the second ## is evaluated first, though all
compilers I have tested do not do that. Under the interpretation that
concatenation happens again, if the first ## is evaluated first then
+<placemarker>####+ should become +##+ and then one preprocessing
token ++. Clang appears to do this, so it returns one from this
program. GCC, EDG, and TCC all return zero instead indicating that
they did not concatenate the + preprocessing tokens but did still
remove the ## between the + preprocessing tokens. MSVC like
before crashes when attempting to preprocess this macro with its new
preprocessor.