Have you ever wanted to write a “for each” loop over all the args of a variadic macro? Or have you ever wanted to overload a macro on the number of arguments? (If you’re saying to yourself, “good grief, why?” — I’ll describe a use case at the bottom of this post.)
I learned how to do this today, and I wanted to blog about it to cement the technique in my own mind. (And I hereby put all the code I show here into the public domain.)

What happened when I decided to learn this technique. I’m trying to spare you… :-) Image credit: xkcd.com
Simple variadic macros
The first piece of magic you need to do something like this is __VA_ARGS__
. This allows you to write macros that take an arbitrary number of arguments, using ...
to represent the macro’s parameters:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define eprintf(fmt, …) \ | |
fprintf(stderr, fmt, __VA_ARGS__) |
Nice. __VA_ARGS__
is a standard feature of C99, and I’ve known about it for a long time. I’ve also known about GCC (and Clang’s) extension, which attaches special meaning to ##__VA_ARGS__
if it’s preceded by a comma–it removes the comma if ##__VA_ARGS__
expands to nothing. If I change my macro definition to:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define eprintf(fmt, …) \ | |
fprintf(stderr, fmt, ##__VA_ARGS__) |
…I can now call eprintf("hello, world");
without a complaint from the compiler.
But it’s not enough
That doesn’t let me do a “for each” loop, though. All the args that I pass are expanded, but I can’t do anything with them, individually. I have no names for my macro’s parameters–just the anonymous ….
I went poking around, not expecting to find a solution, but I was pleasantly surprised.