cpp: Stringizing
1
1 3.4 Stringizing
1 ===============
1
1 Sometimes you may want to convert a macro argument into a string
1 constant. Parameters are not replaced inside string constants, but you
1 can use the '#' preprocessing operator instead. When a macro parameter
1 is used with a leading '#', the preprocessor replaces it with the
1 literal text of the actual argument, converted to a string constant.
1 Unlike normal parameter replacement, the argument is not macro-expanded
1 first. This is called "stringizing".
1
1 There is no way to combine an argument with surrounding text and
1 stringize it all together. Instead, you can write a series of adjacent
1 string constants and stringized arguments. The preprocessor replaces
1 the stringized arguments with string constants. The C compiler then
1 combines all the adjacent string constants into one long string.
1
1 Here is an example of a macro definition that uses stringizing:
1
1 #define WARN_IF(EXP) \
1 do { if (EXP) \
1 fprintf (stderr, "Warning: " #EXP "\n"); } \
1 while (0)
1 WARN_IF (x == 0);
1 ==> do { if (x == 0)
1 fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);
1
1 The argument for 'EXP' is substituted once, as-is, into the 'if'
1 statement, and once, stringized, into the argument to 'fprintf'. If 'x'
1 were a macro, it would be expanded in the 'if' statement, but not in the
1 string.
1
1 The 'do' and 'while (0)' are a kludge to make it possible to write
1 'WARN_IF (ARG);', which the resemblance of 'WARN_IF' to a function would
1 make C programmers want to do; see ⇒Swallowing the Semicolon.
1
1 Stringizing in C involves more than putting double-quote characters
1 around the fragment. The preprocessor backslash-escapes the quotes
1 surrounding embedded string constants, and all backslashes within string
1 and character constants, in order to get a valid C string constant with
1 the proper contents. Thus, stringizing 'p = "foo\n";' results in
1 "p = \"foo\\n\";". However, backslashes that are not inside string or
1 character constants are not duplicated: '\n' by itself stringizes to
1 "\n".
1
1 All leading and trailing whitespace in text being stringized is
1 ignored. Any sequence of whitespace in the middle of the text is
1 converted to a single space in the stringized result. Comments are
1 replaced by whitespace long before stringizing happens, so they never
1 appear in stringized text.
1
1 There is no way to convert a macro argument into a character
1 constant.
1
1 If you want to stringize the result of expansion of a macro argument,
1 you have to use two levels of macros.
1
1 #define xstr(s) str(s)
1 #define str(s) #s
1 #define foo 4
1 str (foo)
1 ==> "foo"
1 xstr (foo)
1 ==> xstr (4)
1 ==> str (4)
1 ==> "4"
1
1 's' is stringized when it is used in 'str', so it is not
1 macro-expanded first. But 's' is an ordinary argument to 'xstr', so it
11 is completely macro-expanded before 'xstr' itself is expanded (⇒
Argument Prescan). Therefore, by the time 'str' gets to its argument,
1 it has already been macro-expanded.
1