C/C++ macro string concatenation
If they're both strings you can just do:
#define STR3 STR1 STR2
This then expands to:
#define STR3 "s" "1"
and in the C language, separating two strings with space as in "s" "1"
is exactly equivalent to having a single string "s1"
.
You don't need that sort of solution for string literals, since they are concatenated at the language level, and it wouldn't work anyway because "s""1" isn't a valid preprocessor token.
[Edit: In response to the incorrect "Just for the record" comment below that unfortunately received several upvotes, I will reiterate the statement above and observe that the program fragment
#define PPCAT_NX(A, B) A ## BPPCAT_NX("s", "1")
produces this error message from the preprocessing phase of gcc: error: pasting ""s"" and ""1"" does not give a valid preprocessing token
]
However, for general token pasting, try this:
/* * Concatenate preprocessor tokens A and B without expanding macro definitions * (however, if invoked from a macro, macro arguments are expanded). */#define PPCAT_NX(A, B) A ## B/* * Concatenate preprocessor tokens A and B after macro-expanding them. */#define PPCAT(A, B) PPCAT_NX(A, B)
Then, e.g., both PPCAT_NX(s, 1)
and PPCAT(s, 1)
produce the identifier s1
, unless s
is defined as a macro, in which case PPCAT(s, 1)
produces <macro value of s>1
.
Continuing on the theme are these macros:
/* * Turn A into a string literal without expanding macro definitions * (however, if invoked from a macro, macro arguments are expanded). */#define STRINGIZE_NX(A) #A/* * Turn A into a string literal after macro-expanding it. */#define STRINGIZE(A) STRINGIZE_NX(A)
Then,
#define T1 s#define T2 1STRINGIZE(PPCAT(T1, T2)) // produces "s1"
By contrast,
STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"#define T1T2 visit the zooSTRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"
Hint: The STRINGIZE
macro above is cool, but if you make a mistake and its argument isn't a macro - you had a typo in the name, or forgot to #include
the header file - then the compiler will happily put the purported macro name into the string with no error.
If you intend that the argument to STRINGIZE
is always a macro with a normal C value, then
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
will expand it once and check it for validity, discard that, and then expand it again into a string.
It took me a while to figure out why STRINGIZE(ENOENT)
was ending up as "ENOENT"
instead of "2"
... I hadn't included errno.h
.