Zehanort
Zehanort

Reputation: 508

variadic macro that handles last argument in a different way

I was wandering if there is a way to define a variadic macro that handles its last argument in a different way.

For example, can I define a macro that prints a custom separator after every argument except for the last one?

i.e. how to define MACRO:

MACRO(a, lot, of, bars)

In order to produce this output:

a|lot|of|bars

(EDIT: it was pointed out to me by the comments that the case of , as separator is trivial)

Upvotes: 0

Views: 227

Answers (2)

jxh
jxh

Reputation: 70382

You can apply the macro argument counting trick. For up to five macro arguments (the original answer supported 4 macro arguments, so you can view the diff to see how to extend the macro for additional arguments):

#define MACRO(...) MACRO_X(__VA_ARGS__,5,4,3,2,1)(__VA_ARGS__)

#define MACRO_X(_5,_4,_3,_2,_1,X,...) MACRO_##X

#define MACRO_5(X,...) X|MACRO_4(__VA_ARGS__)
#define MACRO_4(X,...) X|MACRO_3(__VA_ARGS__)
#define MACRO_3(X,...) X|MACRO_2(__VA_ARGS__)
#define MACRO_2(X,...) X|MACRO_1(__VA_ARGS__)
#define MACRO_1(X,...) X

To create a string, you can use the "stringify" operator:

#define STR2(X) STR(X)
#define STR(X) #X

So:

puts(STR2(MACRO(a,lot,of,bars)));

Upvotes: 3

M.M
M.M

Reputation: 141544

If the output does not need to be stringised, then you can produce an equivalent expression relatively simply:

#define MACRO(...) BIGMACRO(__VA_ARGS__,0,0,0,0,0,0,0,0)
#define BIGMACRO(a0,a1,a2,a3,a4,a5,a6,a7,...) a0|a1|a2|a3|a4|a5|a6|a7

so MACRO(a,lot,of,bars) expands to a|lot|of|bars|0|0|0|0 , which has the same type and value as a|lot|of|bars.

Upvotes: 2

Related Questions