Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c

macros

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 ?

like image 315
amanjiang Avatar asked Sep 11 '15 10:09

amanjiang


People also ask

How do you define a string macro?

We can create two or more than two strings in macro, then simply write them one after another to convert them into a concatenated string. The syntax is like below: #define STR1 "str1" #define STR2 " str2" #define STR3 STR1 STR2 //it will concatenate str1 and str2. Input: Take two strings.

Can macro return a value?

Macros just perform textual substitution. They can't return anything - they are not functions.

What is a macro argument?

Macro Arguments (DEFINE-! ENDDEFINE command) The macro definition can include macro arguments, which can be assigned specific values in the macro call. There are two types of arguments: keyword and positional. Keyword arguments are assigned names in the macro definition; in the macro call, they are identified by name.

What does ## mean in macro?

The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.


1 Answers

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++.

like image 191
M Oehm Avatar answered Sep 22 '22 05:09

M Oehm