Passing string as #define and resolving it as string
Sometimes, it’s required to pass string that will be passed as preprocessor variable so we can make some choices during compilation phase. If you try to pass string as preprocessor variable, and will try to use it inside C string literals, it will fail.
#include <stdio.h> #ifndef VALUE #error VALUE is not defined #endif int main(int argc, char **argv) { const char* str = "VALUE"; printf("%s\n", str); return 0; }
and, of course, I learned that the hard way. It’s simple, string literals are not treated by preprocessor.
> gcc -DVALUE=hi_there -o main ./main.c > ./main VALUE
The only way to solve it is to use Stringification.
What you eventually have to do to make it work, is following
#include <stdio.h> #ifndef VALUE #error VALUE is not defined #endif #define string_value_(x) #x #define string_value(x) string_value_(x) int main(int argc, char **argv) { const char* str = string_value(VALUE); printf("%s\n", str); return 0; }
and you can get what you wanted
> gcc -DVALUE=hi_there -o main ./main.c > ./main hi_there
This one will still fail for values with :. E.g.: http://my.address will produce
> gcc -DVALUE=http://my.address -o main ./main.c > ./main http:
in order to fix that, we have to change a little bit macro, and the way we are passing variable
#include <stdio.h> #ifndef VALUE #error VALUE is not defined #endif #define string_value_(x) x #define string_value(x) string_value_(x) int main(int argc, char **argv) { const char* str = string_value(VALUE); printf("%s\n", str); return 0; }
and we have to make sure to pass variable surrounded with \".
> gcc -DVALUE=\"http://my.address\" -o main ./main.c > ./main http://my.address