17

I have a macro like this:

#define C( a... ) ( char *[] ){ a, 0 }

This works for non-empty arguments:

C( "a", "b" ) => ( char *[] )( "a", "b", 0 }

But I want to remove the trailing comma when provided with an empty argument:

C() => ( char *[] ){ , 0 }

Is this possible?

Cinolt Yuklair
  • 397
  • 2
  • 11
  • 1
    There is no portable way to do this at the moment. (I believe there's a pending proposal that would allow you to construct something like this, though.) – Kerrek SB Sep 02 '16 at 12:06
  • I mean, take a look at Boost.Preprocessor, maybe there is *some* kind of magic that can achieve this. (Which ought to work in C, too.) – Kerrek SB Sep 02 '16 at 12:18
  • Meh that's OK, I was just curious if it was possible. Since it's not, I'd just define something like `#define C0 ( char *[] ){ 0 }` – Cinolt Yuklair Sep 02 '16 at 12:25
  • Instead of removing the trailing comma, do not add it in the first place. See my strategy on: [How to easily create fully “variadic” functions with C++ 98 standard?](https://stackoverflow.com/questions/59331919/how-to-easily-create-fully-variadic-functions-with-c-98-standard/). – Evandro Coan Dec 15 '19 at 00:09

3 Answers3

5

At least in GCC 5.4.0, on Cygwin (default -std=gnu11), this appears to do what you want (assuming I understand your question correctly):

#define C( a... ) ( char *[] ){ a 0 }
                                 ^ no comma!    
C( "a", "b", ) 
           ^ comma here
=> ( char *[] )( "a", "b", 0 }

C() 
=> ( char *[] ){ 0 }

Tested with gcc -E and no other command-line options.

Edit As @KerrekSB noted, this is not portable. The GCC preprocessor docs have this to say (emphasis added):

The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter [as in this situation-Ed.], as it is meaningless to try to distinguish whether no argument at all is an empty argument or a missing argument. In this case the C99 standard is clear that the comma must remain, however the existing GCC extension used to swallow the comma. So CPP retains the comma when conforming to a specific C standard, and drops it otherwise.

So the above works fine in GCC, but might not on other compilers. However, it does work for me with gcc -std=c90 -E (or c99, or c11).

cxw
  • 16,685
  • 2
  • 45
  • 81
  • It's a minor nuisance in an aesthetic sense to have to type the trailing comma into each invocation of the macro, which personally speaking isn't worth it, but technically looks to be the only (for now) actual workaround for this question. – Cinolt Yuklair Sep 02 '16 at 15:27
5

Check out GCC's __VA_OPT__() function macro that can be used within a variadic macro.

#define C(...) (char *[]) { __VA_ARGS__ __VA_OPT__(,) 0 }

C("a", "b");   expands to (char *[]) { "a", "b" , 0 };
C();           expands to (char *[]) { 0 };

The arguments passed to __VA_OPT__() will only be expanded if __VA_ARGS__ is non-empty.

user924037
  • 141
  • 1
  • 6
0

Try this

#define _C(a, ...)      __VA_ARGS__
#define C(...)          (char *[]){ _C(0, ##__VA_ARGS__, 0) }

C("a", "b") => (char *[]){ "a", "b", 0 };
C() => (char *[]){ 0 };
s30904
  • 1
  • 1