I started programming in C 15 years ago, but I don’t consider myself an expert or anything like that. There are just too many aspects of C I’m not comfortable with. One of those is the Preprocessor.

Something I never fully understood is the STRINGIFY macro hack. The preprocessor has a “#” operator that turns its argument into a string.

#define STRINGIFY(x) #x
#define HELLO(x) "Hello " #x

STRINGIFY(foo) is expanded to “foo”, HELLO(world) is expanded to “Hello " “world”. So far, so good, but when you try to stringify another macro it doesn’t work as expected:

#define STRINGIFY(x) #x
#define FOO bar
STRINGIFY(FOO) /* This will output ... "FOO", not "bar" */
STRINGIFY(__LINE__) /* This will output "__LINE__", not "4" */

If you look for a solution on the interweb, the answer is usually to use another auxiliary macro, and it “magically” works:

#define STRINGIFY2(x) #x
#define FOO bar
STRINGIFY(FOO) /* This wil output "bar", why?!?!? */

Why does that work? Because the preprocessor doesn’t expand macro’s arguments, but the result of the expansion can be expanded afterward. Here’s what happen:

  1. STRINGIFY(FOO) is expanded to STRINGIFY2(FOO) because of #define STRINGIFY(x) STRINGIFY2(x)
  2. FOO is expanded to bar using #define FOO bar, we now have STRINGIFY2(bar)
  3. STRINGIFY2(bar) is expanded to “bar”