Patrick Wright
Patrick Wright

Reputation: 1663

C Macro Stringify Only If Argument is Present

I am trying to figure out how to write a preprocessor macro which will "stringify" its argument only if an argument is present

For example:

STRINGIFY(foo) -> "foo"
STRINGIFY() ->

In my very basic example:

#define STRINGIFY(x) #x

Calling STRINGIFY() results in "" rather than nothing at all (which is what I want)

How can this be achieved?

EDIT

As An example of why I want this behavior, I am using the macro to generate an initializer for an array of strings as such

const char* STRINGS[] = {MAP_LIST(STRINGIFY, __VA_ARGS__)}; 

Where MAP_LIST comes from the following project: https://github.com/swansontec/map-macro

If my VA_ARGS lsit has items in it, you end up with, for example, the following:

const char* STRINGS[] = {"a", "b", "c"}; 

But if VA_ARGS is empty, I end up with:

const char* STRINGS[] = {""};

Because, when you "stringify" an empty argument, it gives you an empty string.

Upvotes: 0

Views: 486

Answers (1)

KamilCuk
KamilCuk

Reputation: 141493

how to write a preprocessor macro which will "stringify" its argument only if an argument is present

You can do a variadic macro and put a macro with () that will expand to a comma (or specific count of commas) and put __VA_ARGS__ between that macro and () and then overload on the count of arguments.

#define TRIGGER_PARENTHESIS(...)  ,
#define STRINGIFY_0()
#define STRINGIFY_1(a)  #a
#define STRINGIFY_N2(_0,_1,N,...) STRINGIFY_##N
#define STRINGIFY_N(...) STRINGIFY_N2(__VA_ARGS__)
#define STRINGIFY(...) STRINGIFY_N(TRIGGER_PARENTHESIS __VA_ARGS__ (),0,1)(__VA_ARGS__)

See A way to count the number of __VA_ARGS__ arguments, including 0, without compiler specific constructs for a more roboust method.

With a compiler with __VA_OPT__ and in newer C++, it's just:

#define STRINGIFY(...) __VA_OPT__(#__VA_ARGS__)

As noted in the comments, your use case is invalid. If the result of MAP_LIST(STRINGIFY, __VA_ARGS__) would be empty, then it would result in:

const char* STRINGS[] = {}; 

which is invalid C code, because Is an empty initializer list valid C code? and What happens if I define a 0-size array in C/C++? . Both zero sized arrays and empty initializer lists are extensions in GNU C compiler.

Upvotes: 1

Related Questions