There is a well-known problem with empty args for variadic macros in C99.
example:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
The use of BAR()
above is indeed incorrect according to the C99 standard, since it will expand to:
printf("this breaks!",);
Note the trailing comma - not workable.
Some compilers (eg: Visual Studio 2010) will quietly get rid of that trailing comma for you. Other compilers (eg: GCC) support putting ##
in front of __VA_ARGS__
, like so:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
But is there a standards-compliant way to get this behavior? Perhaps using multiple macros?
Right now, the ##
version seems fairly well-supported (at least on my platforms), but I'd really rather use a standards-compliant solution.
Pre-emptive: I know I could just write a small function. I'm trying to do this using macros.
Edit: Here is an example (though simple) of why I would want to use BAR():
#define BAR(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
This automatically adds a newline to my BAR() logging statements, assuming fmt
is always a double-quoted C-string. It does NOT print the newline as a separate printf(), which is advantageous if the logging is line-buffered and coming from multiple sources asynchronously.
BAR
instead ofFOO
in the first place?__VA_OPT__
keyword. This has already been "adopted" by C++, so I expect C will follow suit. (don't know whether that means it was fast-tracked into C++17 or if it's set for C++20 though)