I'd like to do something like this:
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define MULTIARG() ARG1, ARG2, ARG3
NEED3ARGS( MULTIARG() )
And I expected it to output something like:
( "[" "ARG1" " + " "ARG2" " + " "ARG3" "]" )
But instead I have:
$ cpp multiarg.c
# 1 "multiarg.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "multiarg.c"
multiarg.c:4:23: error: macro "NEED3ARGS" requires 3 arguments, but only 1 given
NEED3ARGS
Is there a way to do what I want using ANSI-C/GNU GCC and the C preprocessor?
Thanks!
You need some indirection. With C99:
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define INVOKE_NEED3ARGS(...) NEED3ARGS(__VA_ARGS__)
#define MULTIARG() ARG1, ARG2, ARG3
INVOKE_NEED3ARGS( MULTIARG() )
(C99 isn't strictly required; you can replace the variadic macro with a fixed-arity macro.)
If you need to compile your source using Visual C++, you'll need even more indirection (because of a compiler bug):
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define INVOKE_NEED3ARGS_(...) NEED3ARGS __VA_ARGS__
#define INVOKE_NEED3ARGS(...) INVOKE_NEED3ARGS_((__VA_ARGS__))
#define MULTIARG() ARG1, ARG2, ARG3
INVOKE_NEED3ARGS( MULTIARG() )
As for why indirection is needed: a macro argument is not evaluated and macro-replaced until it is substituted into the replacement list. So, when you try NEED3ARGS(MULTIARG())
, MULTIARG()
will not be evaluated until after macro invocation has begun, so it's treated as a single argument.
The INVOKE_NEED3ARGS
macro ensures that its arguments are completely evaluated before NEED3ARGS
is invoked. The __VA_ARGS__
is substituted by the macro-replaced arguments to INVOKE_NEED3ARGS
, which is ARG1, ARG2, ARG3
, then NEED3ARGS
is invoked with those arguments.
Yes,
#define NEED3ARGS(a1,a2,a3) ( "[" #a1 " + " #a2 " + " #a3 "]" )
#define MULTIARG() ARG1, ARG2, ARG3
#define NEED1ARG(ARG) NEED3ARGS(ARG)
NEED1ARG( MULTIARG() )
You need to wrap it in another macro call so the argument gets expanded before NEED3ARGS
is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With