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