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 STRINGIFY(foo) #define HELLO(x) "Hello " #x HELLO(world)
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 STRINGIFY(x) STRINGIFY2(x) #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:
- STRINGIFY(FOO) is expanded to STRINGIFY2(FOO) because of #define STRINGIFY(x) STRINGIFY2(x)
- FOO is expanded to bar using #define FOO bar, we now have STRINGIFY2(bar)
- STRINGIFY2(bar) is expanded to “bar”