I'm having a problem with optional arguments in #define statements in C, or more specifically with gcc 4.2:
bool func1(bool tmp) { return false; }
void func2(bool tmp, bool tmp2) {}
#define CALL(func, tmp, ...) func(tmp, ##__VA_ARGS__)
int main() {
// this compiles
CALL(func2, CALL(func1, false), false);
// this fails with: Implicit declaration of function 'CALL'
CALL(func2, false, CALL(func1, false));
}
That's obviously a contrived example, but does show the problem. Does anyone know how I can get the optional arguments to "resolve" correctly?
Additional information:
If I remove the ##
before __VA_ARGS__
, and do something like this:
bool func2(bool tmp, bool tmp2) { return false; }
#define CALL(func, tmp, ...) func(tmp, __VA_ARGS__)
int main() {
CALL(func2, false, CALL(func2, false, false));
}
That compiles, but it no longer works with zero arguments since it would resolve to func(tmp, )
EDIT: Right after converting all of my code to rely on P99 instead of what I had earlier (which ended up breaking my code considerably, whoops), I accidentally discovered that this works:
bool func1(bool tmp) { return false; }
void func2(bool tmp, bool tmp2) {}
#define CALL2(func, tmp, p...) func(tmp, ##p)
#define CALL(func, tmp...) CALL2(func, tmp)
int main() {
// works
CALL(func2, CALL(func1, false), false);
// ...also works
CALL(func2, false, CALL(func1, false));
}
Compiles and works with any number of parameters (and the correct values are passed in and returned), but... is this supposed to be legal?
The ##
operator does exact token substitution, so in that case it's trying to send the token "CALL(func1, false)"
as the last argument to the func1
C function.
The problem with this is that CALL
is a macro, and you cannot nest variadic macro invocations within a ##__VA_ARGS__
list.
The reason why it works when the inner macro is passed as a named argument is because the preprocessor will parse named arguments for inner macros, but not ##__VA_ARGS__
lists, where there is just simple token substitution.
One way to solve this is to assign the result of the inner CALL
to a placeholder variable and then pass that along to the macro.
int main() {
CALL(func2, CALL(func1, false), false);
bool result = CALL(func1, false);
CALL(func2, false, result);
}
Another way to solve this is to just use __VA_ARGS__
as the only argument to the func
function, and that would allow you to pass in nested macro invocations, like so:
#define CALL(func, ...) func(__VA_ARGS__)
int main() {
CALL(func2, false, CALL(func2, false, false));
}
Let's analyze your dilemma in a bit more detail:
CALL(func2, false, CALL(func1, false))
In this particular macro invocation, CALL
is now ("func2", "tmp", CALL(func1, false))
So it tries to invoke func1
, passing in tmp
, and, well, CALL(func1, false)
.
This is where the line is drawn between the preprocessor and the actual C compiler.
The preprocessor, once it starts doing substitution, it's done parsing, so the compiler receives CALL(func1, false)
as an actual C function, not a macro, because the compiler doesn't know about macros, only the preprocessor does.
You are using a gcc extension with the , ##
construct. It is probably not a good idea to use that if you have portability in mind.
With a little bit of effort you can construct macros that may react on the number of arguments they receive and do the right replacement. P99 provides helpers for that:
#define CALL(...) P99_IF_EQ_2(P99_NARG(__VA_ARGS__))(dosomethingwithtwo(__VA_ARGS__))(dosomethingwithmore(__VA_ARGS__))
But in your case I think there is an easy solution:
#define CALL(func, ...) func(__VA_ARGS__)
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