#define STR1 \"s\"
#define STR2 \"1\"
#define STR3 STR1 ## STR2
Is it possible to concatenate have STR3 == \"s1\"? You can do this by passing args to another Macro function. But is there a direct way?
#define STR1 \"s\"
#define STR2 \"1\"
#define STR3 STR1 ## STR2
Is it possible to concatenate have STR3 == \"s1\"? You can do this by passing args to another Macro function. But is there a direct way?
If they\'re both strings you can just do:
#define STR3 STR1 STR2
The preprocessor automatically concatenates adjacent strings.
EDIT:
As noted below, it\'s not the preprocessor but the compiler that does the concatenation.
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. 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., PPCAT(s, 1)
produces the identifier s1
.
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 1
STRINGIZE(PPCAT(T1, T2)) // produces \"s1\"
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
.