Home > Software design >  gcc preprocessor variables to string literals
gcc preprocessor variables to string literals

Time:12-05

I know there a bazillion question like this, but I couldn't find a good answer. I'm compiling a source with preprocessor tokens defined in CFLAGS:

-D X=string1 -D Y=string2

I'm trying to create a string literal in my header file that combines these two values and use it in my sources like:

printf("%s", COMBINED);

But this doesn't work:

 #define _COMBINED(x, y) x ## y
 #define COMBINED _COMBINED(X, Y)

Thanks

CodePudding user response:

To pass a string-ized token to a concatenating macro, you need a level of indirection. That means you pass it to a different macro.

#define COMBINED(a, b) (a##b)
#define COMBINE(a, b) COMBINED(a, b)

Then you pass off the params in COMBINE, in your case, X and Y

int main (void)  // best practice is to void-erize non-param-ed functions
{
    printf("%s\n", COMBINE(X,Y));
}

If you really want to do it "directly", you can do it like this:

#define DEFAULT_COMBINE COMBINE(X,Y)

And call:

printf("%s\n", DEFAULT_COMBINE);

Now, let's end with a caveat, as this is also about "best practice" so it's quite important even though it might not seem that way to you, it is, trust me on this one. Never ever, and i mean NEVER EVER start off your own preprocessor defines or constants with an underscore. Never, under any circumstances. Even if your brother works at Microsoft or worked on the Linux kernel.

In the standard and best-practice C and C world, the _COMBINED macro is illegal. No, not invalid, it just means you shouldn't name it like that. The short version is that constants, intrisincs and macros startign with an underscore are compiler or internal only. It's a "marker" to know that it's not something someone set.

CodePudding user response:

You did not show an example how you call the compiler, so I made some experiments. Since commas (and other non-alphanumerical characters) will get in the way, it boiled down to the need to pass quotation marks as delimiters of the replacement text of the macros.

So I think your real issue is how to pass the strings in an equivalent way to:

#define X "hello, "
#define Y "world!"

Note: Here extra difficult because of comma and exclamation mark.

If the macro replacement text is passed including the quotation marks, the C source gets simple. In C, you concatenate string without any intermediate operator. "abc" "def" is the same as "abcdef".

#include <stdio.h>

#define COMBINED X Y

int main(void) {
    printf("%s\n", COMBINED);
}

Depending on your real use case, you could even simplify this to:

#include <stdio.h>

int main(void) {
    printf("%s\n", X Y);
}

In a Bash you need to escape the command line arguments like this, for example:

gcc -Wall -pedantic -D 'X="hello, "' -D 'Y="world!"' combine.c -s -O3 -o combine

For Windows' CMD I cannot present an example, since today I have no access to a Windows machine.

  • Related