amanjiang
amanjiang

Reputation: 1283

Convert a macro argument into a string constant and take into account commas

Say I have a C macro-defined product version like this:

#define FOO_VERSION 1,0,0,1

And I want to print it at run-time:

#define STRING_VALUE(x) #x

int main()
{
    std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}

This will output a string "FOO_VERSION", not "1,0,0,1". The macro argument 'FOO_VERSION' is not replaced. So I try it again like this:

#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(x) #x

int main()
{
    std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}

It works, in Visual C++ 2013.

This is a cross-platform application although there are only five lines of code. When I use clang to compile the code, a compile- time error appears: "too many arguments provided to function-like macro invocation". I guess the reason is the comma defined in 'FOO_VERSION'. So the third version:

#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(a, b, c, d) #a "," #b "," #c "," #d

int main()
{
    std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}

This code works in clang, but Visual C++ will output a warning: "not enough actual parameters for macro 'STRING_VALUE__'" at compile-time, of course the run-time output is not right.

My question: is this pre-processor behavior defined ? Can I have a universal version of STRING_VALUE macro ?

Upvotes: 6

Views: 1177

Answers (1)

M Oehm
M Oehm

Reputation: 29126

You can treat the argument as a single variadic macro:

#define FOO_VERSION 1,0,0,1

#define STRING_VALUE(...) STRING_VALUE__(__VA_ARGS__)
#define STRING_VALUE__(...) #__VA_ARGS__

This seems to work with gcc and Visual C++.

Upvotes: 11

Related Questions