I'm trying to make some kind of a simple system that calculates the number of builds, including this info in .rc file (for windows) and met the problem. Here it is:
#define QUOTE(s) #s
#define A 0,0,0,1
#define A_STR QUOTE(A)
Expanding of A_STR: "A"
but not "0,0,0,1"
as I expected.
Well, I need A_STR
to be a string representation of A
(that's what windres
expects to see in .rc file), but I can't find the way to do this.
I've already tried smth like #define A_STR #A
but it simply expands to #0,0,0,1
.
I also tried using qmake like this: DEFINES *= A_STR="<here-is-how-I-get-version>"
but gcc
gets it without quotes and I've got the same problem.
When a C preprocessor macro is expanded, its parameters are expanded to their literal arguments, so s
would be expanded to A
when your QUOTE(s)
taking argument A
is expanded. Normally, after this expansion is complete, the expanded text is then scanned again to expand any macros embedded therein, so this would cause the A
to expand to 0,0,0,1
. However, when the stringification operator #
is used to stringify the following text, that stringification happens first, so the following text never gets a chance to be expanded, thus you get stringified "A"
as the final expansion of A_STR
.
This problem is normally solved by introducing a second level of indirection, which gives the initial macro argument a second chance to expand:
#define QUOTE2(A) #A
#define QUOTE(A) QUOTE2(A)
However, this would not actually work for your case, because in the first-level expansion the A
would expand to 0,0,0,1
, which would be taken as four arguments to QUOTE2()
, and thus would be rejected as an invalid macro call.
You can solve this with variadic macro arguments and __VA_ARGS__
:
#define QUOTE2(...) #__VA_ARGS__
#define QUOTE(...) QUOTE2(__VA_ARGS__)