I would like to pass 2 arguments to a macro using another macro:
#define A_AND_B 5,1
#define ADD(a, b) a b
int add_them(void)
{
int result = ADD(A_AND_B);
return result ;
}
I would hope that expands to
int result = 5 1;
and I get 6. Instead I get
Error 'ADD' undeclared (first use in this function)
Error macro "ADD" requires 2 arguments, but only 1 given
Is there a way around this?
CodePudding user response:
As is often the case, you need an extra level of (macro) indirection:
#define A_AND_B 5,1
#define ADD(...) ADD_(__VA_ARGS__)
#define ADD_(a, b) a b
int add_them(void)
{
int result = ADD(A_AND_B);
return result ;
}
ADD
is defined as variadic so that it will work as either ADD(A_AND_B)
or ADD(A, B)
.
This works because __VA_ARGS__
in the replacement body of ADD
is replaced with the actual arguments before the replacement body is scanned for macros.
CodePudding user response:
Per C 2018 6.10.3.1, a compiler first identifies the arguments for a function-like macro and then performs macro replacement on the arguments, followed by macro replacement for the function-like macro. This means that, in ADD(A_AND_B)
, the argument is identified as A_AND_B
before it is replaced with 5,1
. As the macro invocation has only this single argument and the macro is defined to have two parameters, an error is diagnosed.
Given your definition of ADD
, there is no way to change this behavior in a compiler that conforms to the C standard.
You can instead use another macro to expand the arguments and apply the desired macro:
#define Apply(Macro, Arguments) Macro(Arguments)
then int result = Apply(ADD, A_AND_B);
will work. That will identify ADD
and A_AND_B
as arguments to Apply
. Then it will expand those, producing an unchanged ADD
and 5,1
. Then the macro replacement for Apply
produces ADD(5,1)
. Then this is again processed for macro replacement, which replaces ADD(5,1)
in the ordinary way.
Note that good practice is usually to define ADD
as #define ADD(a, b) ((a) (b))
to avoid unexpected interactions with other operators neighboring the use of the macro.