Related
There are plenty of questions discussing how to count __VA_ARGS__ and the problem of zero arguments (e.g. [1] and [2]). However, answers to these questions usually are either not portable, since they use the GCC specific ##__VA_ARGS__ to account for the "0 arguments" case, or they are portable, but cannot account for 0 arguments (both COUNT_ARGS() and COUNT_ARGS(something) are evaluated to 1).
Is there a solution that can count the number of arguments in __VA_ARGS__, including 0, that can work in any C compiler complying to the standard?
After some research, I found a blog post by Jens Gustedt named "Detect empty macro arguments" (which I found as a comment by him in this answer). Together with the counting solution found in another answer by H Walters (which is similar to this one) we can build a solution that should work in any C99 compiler. The code below is a unification of these two methods.
One noteworthy change I made was adding extra EXPAND macros. As discussed in this question, MSVC does not expand __VA_ARGS__ like most other compilers, so an extra step of expansion is necessary.
/* NOTE: In these macros, "1" means true, and "0" means false. */
#define EXPAND(x) x
#define _GLUE(X,Y) X##Y
#define GLUE(X,Y) _GLUE(X,Y)
/* Returns the 100th argument. */
#define _ARG_100(_,\
_100,_99,_98,_97,_96,_95,_94,_93,_92,_91,_90,_89,_88,_87,_86,_85,_84,_83,_82,_81, \
_80,_79,_78,_77,_76,_75,_74,_73,_72,_71,_70,_69,_68,_67,_66,_65,_64,_63,_62,_61, \
_60,_59,_58,_57,_56,_55,_54,_53,_52,_51,_50,_49,_48,_47,_46,_45,_44,_43,_42,_41, \
_40,_39,_38,_37,_36,_35,_34,_33,_32,_31,_30,_29,_28,_27,_26,_25,_24,_23,_22,_21, \
_20,_19,_18,_17,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,X_,...) X_
/* Returns whether __VA_ARGS__ has a comma (up to 100 arguments). */
#define HAS_COMMA(...) EXPAND(_ARG_100(__VA_ARGS__, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ,1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0))
/* Produces a comma if followed by a parenthesis. */
#define _TRIGGER_PARENTHESIS_(...) ,
#define _PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define _IS_EMPTY_CASE_0001 ,
/* Returns true if inputs expand to (false, false, false, true) */
#define _IS_EMPTY(_0, _1, _2, _3) HAS_COMMA(_PASTE5(_IS_EMPTY_CASE_, _0, _1, _2, _3))
/* Returns whether __VA_ARGS__ is empty. */
#define IS_EMPTY(...) \
_IS_EMPTY( \
/* Testing for an argument with a comma \
e.g. "ARG1, ARG2", "ARG1, ...", or "," */ \
HAS_COMMA(__VA_ARGS__), \
/* Testing for an argument around parenthesis \
e.g. "(ARG1)", "(...)", or "()" */ \
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__), \
/* Testing for a macro as an argument, which will \
expand the parenthesis, possibly generating a comma. */ \
HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
/* If all previous checks are false, __VA_ARGS__ does not \
generate a comma by itself, nor with _TRIGGER_PARENTHESIS_ \
behind it, nor with () after it. \
Therefore, "_TRIGGER_PARENTHESIS_ __VA_ARGS__ ()" \
only generates a comma if __VA_ARGS__ is empty. \
So, this tests for an empty __VA_ARGS__ (given the \
previous conditionals are false). */ \
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
)
#define _VAR_COUNT_EMPTY_1(...) 0
#define _VAR_COUNT_EMPTY_0(...) EXPAND(_ARG_100(__VA_ARGS__, \
100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81, \
80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61, \
60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41, \
40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21, \
20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))
#define VAR_COUNT(...) GLUE(_VAR_COUNT_EMPTY_, IS_EMPTY(__VA_ARGS__))(__VA_ARGS__)
These are some example outputs:
#define EATER0(...)
#define EATER1(...) ,
#define EATER2(...) (/*empty*/)
#define EATER3(...) (/*empty*/),
#define EATER4(...) EATER1
#define EATER5(...) EATER2
#define MAC0() ()
#define MAC1(x) ()
#define MACV(...) ()
#define MAC2(x,y) whatever
VAR_COUNT() // 0
VAR_COUNT(/*comment*/) // 0
VAR_COUNT(a) // 1
VAR_COUNT(a, b) // 2
VAR_COUNT(a, b, c) // 3
VAR_COUNT(a, b, c, d) // 4
VAR_COUNT(a, b, c, d, e) // 5
VAR_COUNT((a, b, c, d, e)) // 1
VAR_COUNT((void)) // 1
VAR_COUNT((void), c, d) // 3
VAR_COUNT((a, b), c, d) // 3
VAR_COUNT(_TRIGGER_PARENTHESIS_) // 1
VAR_COUNT(EATER0) // 1
VAR_COUNT(EATER1) // 1
VAR_COUNT(EATER2) // 1
VAR_COUNT(EATER3) // 1
VAR_COUNT(EATER4) // 1
VAR_COUNT(MAC0) // 1
VAR_COUNT(MAC1) // 1
VAR_COUNT(MACV) // 1
/* This one will fail because MAC2 is not called correctly. */
VAR_COUNT(MAC2) // error
/* But only if it's at the end spot. */
VAR_COUNT(MACV, MAC1, MAC2) // error
VAR_COUNT(MAC2, MAC1, MACV) // 3
As pointed out by Jens Gustedt in his blog post, this solution has a flaw. Quote:
In fact ISEMPTY should work when it is called with macros as argument that expect 0, 1 or a variable list of arguments. If called with a macro X as an argument that itself expects more than one argument (such as MAC2) the expansion leads to an invalid use of that macro X.
So, if the list passed contains a function-like macro at the end that requires two or more arguments (such as MAC2), VAR_COUNT will fail.
Other than that, I've tested the macros on GCC 9.3.0 and Visual Studio 2019, and it should also work with any C99 (or more recent) compiler.
Any modification that fixes the flaw mentioned above is appreciated.
Need a way to support nested calls in variadic macros with optional argument. same as this but C99 compatible
GNU gcc extension for ## operator prevents nested calls from being expanded, see code below.
#define send(obj, msg, ...) find_method(obj, msg)(obj, ##__VA_ARGS__)
/* Ok */
send(0, "+", 1);
find_method(0, "+")(0, 1);
/* Ok. nested call as macros named argument */
send(send(5, "increment"), "+", 1);
find_method(find_method(5, "increment")(5), "+")(find_method(5, "increment")(5), 1);
/* Fail. nested call as macros variable argument i.e. `send` macro is not expanded */
send(0, "+", send(5, "increment"));
find_method(0, "+")(0, send(5, "increment"));
/*
* preprocess with next commands
*
* gcc-4.9 -Wall -std=c99 -E -c file.c | less
* clang-3.8 -Wall -std=c99 -E -c file.c | less
*/
I've modified Jens Gustedt solution to place optional comma, see code below.
Are there more concise alternatives ?
#define _ARG16( \
_0, _1, _2, _3, _4, \
_5, _6, _7, _8, _9, \
_10, _11, _12, _13, _14, \
_15, ...) _15
#define HAS_COMMA(...) \
_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define _TRIGGER_PARENTHESIS_(...) ,
#define OPTIONAL_COMMA(...) \
_ISEMPTY( \
/* test if there is just one argument, eventually an empty \
one */ \
HAS_COMMA(__VA_ARGS__), \
/* test if _TRIGGER_PARENTHESIS_ together with the argument \
adds a comma */ \
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__), \
/* test if the argument together with a parenthesis \
adds a comma */ \
HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
/* test if placing it between _TRIGGER_PARENTHESIS_ and the \
parenthesis adds a comma */ \
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
)
#define SPACE_SYMBOL
#define COMMA_SYMBOL ,
#define ARG3(_0, _1, _2, ...) _2
#define OPTIONAL_COMMA_FROM(...) ARG3(__VA_ARGS__, SPACE_SYMBOL, COMMA_SYMBOL)
#define PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define _ISEMPTY(_0, _1, _2, _3) \
OPTIONAL_COMMA_FROM(PASTE5(_IS_EMPTY_CASE_, _0, _1, _2, _3))
#define _IS_EMPTY_CASE_0001 ,
#define send(obj, msg, ...) \
find_method(obj, msg)(obj OPTIONAL_COMMA(__VA_ARGS__) __VA_ARGS__)
/* Ok */
send(0, "+", 1);
/* Ok */
send(send(5, "increment"), "+", 1);
/* Ok */
send(0, "+", send(5, "increment"));
Update:
H Walters thanks for idea.
Didn't noticed approach with macros overloading in first place
#define SEND_NO_ARG(obj, msg) find_method(obj, msg)(obj)
#define SEND_ARG(obj, msg, ...) find_method(obj, msg)(obj, __VA_ARGS__)
#define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, \
arg14, arg15, arg16, arg17, arg18, ...) arg18
#define SEND_MACRO_SELECTOR(...) \
GET_18TH_ARG(__VA_ARGS__, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_NO_ARG, )
#define send(...) SEND_MACRO_SELECTOR(__VA_ARGS__)(__VA_ARGS__)
This approach is slightly more concise (10 macros vs 12), and at least to my eyes a bit more organized (more of the macros are general purpose):
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define FIRSTOFMANY(X,...) X
// This can be used as a pattern matcher on the first argument.
// Generally, the first argument is ignored; but if it's
// an object-like macro whose expansion has a comma, it can
// shift a new second argument in that's returned.
// Thus, you can build a "query pattern" as the first argument,
// pass a "default" as the second, and override the default with
// "matched pattern macros".
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(_,X,...) X
// Expands to a count of arguments (min 1, max 15).
#define COUNT(...) COUNT_I(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,)
#define COUNT_I(_,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,X,...) X
#define send(obj, ...) \
find_method(obj, FIRSTOFMANY(__VA_ARGS__,)) \
( \
/* select a macro based on ... count (default SEND_LONG) */ \
SECOND(GLUE(WHEN_SEND_VCNT_EQ_,COUNT(__VA_ARGS__)),SEND_LONG)\
(obj, __VA_ARGS__) \
)
#define SEND_LONG(X,Y,...) X,__VA_ARGS__
// Use FIRSTOFMANY when send's varying arg count is 1
#define WHEN_SEND_VCNT_EQ_1 , FIRSTOFMANY
...it's also C99 compliant (not relying on gnu extensions).
macros overloading technique provides shortest code so far.
#define SEND_NO_ARG(obj, msg) find_method(obj, msg)(obj)
#define SEND_ARG(obj, msg, ...) find_method(obj, msg)(obj, __VA_ARGS__)
#define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, \
arg14, arg15, arg16, arg17, arg18, ...) arg18
#define SEND_MACRO_SELECTOR(...) \
GET_18TH_ARG(__VA_ARGS__, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
SEND_NO_ARG, )
#define send(...) SEND_MACRO_SELECTOR(__VA_ARGS__)(__VA_ARGS__)
GNU gcc extension for ## operator prevents nested calls from being expanded, see code below.
If you're willing to use the gnu extension, here's an even more concise approach:
#define COMMAVA(...) ,##__VA_ARGS__
#define send(obj, msg, ...) find_method(obj, msg)(obj COMMAVA(__VA_ARGS__))
I saw this mechanism to simulate macro overloading recently here .
This is the code used for dispatching:
#define macro_dispatcher(func, ...) \
macro_dispatcher_(func, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(func, nargs) \
macro_dispatcher__(func, nargs)
#define macro_dispatcher__(func, nargs) \
func ## nargs
I don't understand how this works. Why does it need the third macro macro_dispatcher__ to concatenate the arguments? I have tried to eliminate the third macro and replace it with the second one, resulting this code:
#include <stdio.h>
#include "va_numargs.h"
#define macro_dispatcher(func, ...) \
macro_dispatcher_(func, __VA_NUM_ARGS__(__VA_ARGS__))
#define macro_dispatcher_(func, nargs) \
func ## nargs
#define max(...) macro_dispatcher(max, __VA_ARGS__) \
(__VA_ARGS__)
#define max1(a) a
#define max2(a, b) ((a) > (b) ? (a) : (b))
int main()
{
max(1);
max(1, 2);
return 0;
}
va_numargs.h:
#ifndef _VA_NARG_H
#define _VA_NARG_H
#define __VA_NUM_ARGS__(...) \
PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#endif
Which evaluates to this:
int main()
{
max__VA_NUM_ARGS__(1) (1);
max__VA_NUM_ARGS__(1, 2) (1, 2);
return 0;
}
What is happening here? Why isn't __VA_NUM_ARGS__(__VA_ARGS__) replaced with the acutal number of arguments?
The extra step is needed because the token concatenation operator (##) suppresses macro expansion of its operands. Here's a simple example that demonstrates the problem:
#define macro macro_expansion
#define concat(x, y) x ## y
concat(macro, macro)
You might expect the above to produce macro_expansionmacro_expansion, but what you get instead is macromacro. While expanding the right-hand side of concat(), the preprocessor notices that x and y (which are set to macro here) are used as operands to ##, and so does not expand them further.
To work around this, we can add another step:
#define macro macro_expansion
#define concat(x, y) concat_(x, y)
#define concat_(x, y) x ## y
concat(macro, macro)
Now x and y are no longer operands of '##' in the right-hand side of concat(), and are therefore expanded. This means that we get concat_(macro_expansion, macro_expansion), which in turn expands to macro_expansionmacro_expansion.
The stringification operator (#) also suppresses macro expansion by the way.
Here's the relevant part of the C11 spec. (section 6.10.3.1):
A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded.
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.
There is an argument counting trick that you can use.
Here is one standard-compliant way to implement the second BAR() example in jwd's question:
#include <stdio.h>
#define BAR(...) printf(FIRST(__VA_ARGS__) "\n" REST(__VA_ARGS__))
/* expands to the first argument */
#define FIRST(...) FIRST_HELPER(__VA_ARGS__, throwaway)
#define FIRST_HELPER(first, ...) first
/*
* if there's only one argument, expands to nothing. if there is more
* than one argument, expands to a comma followed by everything but
* the first argument. only supports up to 9 arguments but can be
* trivially expanded.
*/
#define REST(...) REST_HELPER(NUM(__VA_ARGS__), __VA_ARGS__)
#define REST_HELPER(qty, ...) REST_HELPER2(qty, __VA_ARGS__)
#define REST_HELPER2(qty, ...) REST_HELPER_##qty(__VA_ARGS__)
#define REST_HELPER_ONE(first)
#define REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__
#define NUM(...) \
SELECT_10TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
#define SELECT_10TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, ...) a10
int
main(int argc, char *argv[])
{
BAR("first test");
BAR("second test: %s", "a string");
return 0;
}
This same trick is used to:
count the number of arguments
expand differently depending on the number of arguments
append to __VA_ARGS__
Explanation
The strategy is to separate __VA_ARGS__ into the first argument and the rest (if any). This makes it possible to insert stuff after the first argument but before the second (if present).
FIRST()
This macro simply expands to the first argument, discarding the rest.
The implementation is straightforward. The throwaway argument ensures that FIRST_HELPER() gets two arguments, which is required because the ... needs at least one. With one argument, it expands as follows:
FIRST(firstarg)
FIRST_HELPER(firstarg, throwaway)
firstarg
With two or more, it expands as follows:
FIRST(firstarg, secondarg, thirdarg)
FIRST_HELPER(firstarg, secondarg, thirdarg, throwaway)
firstarg
REST()
This macro expands to everything but the first argument (including the comma after the first argument, if there is more than one argument).
The implementation of this macro is far more complicated. The general strategy is to count the number of arguments (one or more than one) and then expand to either REST_HELPER_ONE() (if only one argument given) or REST_HELPER_TWOORMORE() (if two or more arguments given). REST_HELPER_ONE() simply expands to nothing -- there are no arguments after the first, so the remaining arguments is the empty set. REST_HELPER_TWOORMORE() is also straightforward -- it expands to a comma followed by everything except the first argument.
The arguments are counted using the NUM() macro. This macro expands to ONE if only one argument is given, TWOORMORE if between two and nine arguments are given, and breaks if 10 or more arguments are given (because it expands to the 10th argument).
The NUM() macro uses the SELECT_10TH() macro to determine the number of arguments. As its name implies, SELECT_10TH() simply expands to its 10th argument. Because of the ellipsis, SELECT_10TH() needs to be passed at least 11 arguments (the standard says that there must be at least one argument for the ellipsis). This is why NUM() passes throwaway as the last argument (without it, passing one argument to NUM() would result in only 10 arguments being passed to SELECT_10TH(), which would violate the standard).
Selection of either REST_HELPER_ONE() or REST_HELPER_TWOORMORE() is done by concatenating REST_HELPER_ with the expansion of NUM(__VA_ARGS__) in REST_HELPER2(). Note that the purpose of REST_HELPER() is to ensure that NUM(__VA_ARGS__) is fully expanded before being concatenated with REST_HELPER_.
Expansion with one argument goes as follows:
REST(firstarg)
REST_HELPER(NUM(firstarg), firstarg)
REST_HELPER2(SELECT_10TH(firstarg, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway), firstarg)
REST_HELPER2(ONE, firstarg)
REST_HELPER_ONE(firstarg)
(empty)
Expansion with two or more arguments goes as follows:
REST(firstarg, secondarg, thirdarg)
REST_HELPER(NUM(firstarg, secondarg, thirdarg), firstarg, secondarg, thirdarg)
REST_HELPER2(SELECT_10TH(firstarg, secondarg, thirdarg, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway), firstarg, secondarg, thirdarg)
REST_HELPER2(TWOORMORE, firstarg, secondarg, thirdarg)
REST_HELPER_TWOORMORE(firstarg, secondarg, thirdarg)
, secondarg, thirdarg
It is possible to avoid the use of GCC's ,##__VA_ARGS__ extension if you are willing to accept some hardcoded upper limit on the number of arguments you can pass to your variadic macro, as described in Richard Hansen's answer to this question. If you do not want to have any such limit, however, to the best of my knowledge it is not possible using only C99-specified preprocessor features; you must use some extension to the language. clang and icc have adopted this GCC extension, but MSVC has not.
Back in 2001 I wrote up the GCC extension for standardization (and the related extension that lets you use a name other than __VA_ARGS__ for the rest-parameter) in document N976, but that received no response whatsoever from the committee; I don't even know if anyone read it. In 2016 it was proposed again in N2023, and I encourage anyone who knows how that proposal is going to let us know in the comments.
Not a general solution, but in the case of printf you could append a newline like:
#define BAR_HELPER(fmt, ...) printf(fmt "\n%s", __VA_ARGS__)
#define BAR(...) BAR_HELPER(__VA_ARGS__, "")
I believe it ignores any extra args that aren't referenced in the format string. So you could probably even get away with:
#define BAR_HELPER(fmt, ...) printf(fmt "\n", __VA_ARGS__)
#define BAR(...) BAR_HELPER(__VA_ARGS__, 0)
I can't believe C99 was approved without a standard way to do this. AFAICT the problem exists in C++11 too.
There is a way to handle this specific case using something like Boost.Preprocessor. You can use BOOST_PP_VARIADIC_SIZE to check the size of the argument list, and then conditionaly expand to another macro. The one shortcoming of this is that it can't distinguish between 0 and 1 argument, and the reason for this becomes clear once you consider the following:
BOOST_PP_VARIADIC_SIZE() // expands to 1
BOOST_PP_VARIADIC_SIZE(,) // expands to 2
BOOST_PP_VARIADIC_SIZE(,,) // expands to 3
BOOST_PP_VARIADIC_SIZE(a) // expands to 1
BOOST_PP_VARIADIC_SIZE(a,) // expands to 2
BOOST_PP_VARIADIC_SIZE(,b) // expands to 2
BOOST_PP_VARIADIC_SIZE(a,b) // expands to 2
BOOST_PP_VARIADIC_SIZE(a, ,c) // expands to 3
The empty macro argument list actually consists of one argument that happens to be empty.
In this case, we are lucky since your desired macro always has at least 1 argument, we can implement it as two "overload" macros:
#define BAR_0(fmt) printf(fmt "\n")
#define BAR_1(fmt, ...) printf(fmt "\n", __VA_ARGS__)
And then another macro to switch between them, such as:
#define BAR(...) \
BOOST_PP_CAT(BAR_, BOOST_PP_GREATER(
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1))(__VA_ARGS__) \
/**/
or
#define BAR(...) BOOST_PP_IIF( \
BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1), \
BAR_1, BAR_0)(__VA_ARGS__) \
/**/
Whichever you find more readable (I prefer the first as it gives you a general form for overloading macros on the number of arguments).
It is also possible to do this with a single macro by accessing and mutating the variable arguments list, but it is way less readable, and is very specific to this problem:
#define BAR(...) printf( \
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__) "\n" \
BOOST_PP_COMMA_IF( \
BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1)) \
BOOST_PP_ARRAY_ENUM(BOOST_PP_ARRAY_POP_FRONT( \
BOOST_PP_VARIADIC_TO_ARRAY(__VA_ARGS__)))) \
/**/
Also, why is there no BOOST_PP_ARRAY_ENUM_TRAILING? It would make this solution much less horrible.
Edit: Alright, here is a BOOST_PP_ARRAY_ENUM_TRAILING, and a version that uses it (this is now my favourite solution):
#define BOOST_PP_ARRAY_ENUM_TRAILING(array) \
BOOST_PP_COMMA_IF(BOOST_PP_ARRAY_SIZE(array)) BOOST_PP_ARRAY_ENUM(array) \
/**/
#define BAR(...) printf( \
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__) "\n" \
BOOST_PP_ARRAY_ENUM_TRAILING(BOOST_PP_ARRAY_POP_FRONT( \
BOOST_PP_VARIADIC_TO_ARRAY(__VA_ARGS__)))) \
/**/
A very simple macro I'm using for debug printing:
#define DBG__INT(fmt, ...) printf(fmt "%s", __VA_ARGS__);
#define DBG(...) DBG__INT(__VA_ARGS__, "\n")
int main() {
DBG("No warning here");
DBG("and we can add as many arguments as needed. %s", "nice!");
return 0;
}
No matter how many arguments are passed to DBG there are no c99 warning.
The trick is DBG__INT adding a dummy param so ... will always have at least one argument and c99 is satisfied.
I ran into a similar problem recently, and I do believe there's a solution.
The key idea is that there's a way to write a macro NUM_ARGS to count the number of arguments which a variadic macro is given. You can use a variation of NUM_ARGS to build NUM_ARGS_CEILING2, which can tell you whether a variadic macro is given 1 argument or 2-or-more arguments. Then you can write your Bar macro so that it uses NUM_ARGS_CEILING2 and CONCAT to send its arguments to one of two helper macros: one which expects exactly 1 argument, and another which expects a variable number of arguments greater than 1.
Here's an example where I use this trick to write the macro UNIMPLEMENTED, which is very similar to BAR:
STEP 1:
/**
* A variadic macro which counts the number of arguments which it is
* passed. Or, more precisely, it counts the number of commas which it is
* passed, plus one.
*
* Danger: It can't count higher than 20. If it's given 0 arguments, then it
* will evaluate to 1, rather than to 0.
*/
#define NUM_ARGS(...) \
NUM_ARGS_COUNTER(__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, \
12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define NUM_ARGS_COUNTER(a1, a2, a3, a4, a5, a6, a7, \
a8, a9, a10, a11, a12, a13, \
a14, a15, a16, a17, a18, a19, a20, \
N, ...) \
N
STEP 1.5:
/*
* A variant of NUM_ARGS that evaluates to 1 if given 1 or 0 args, or
* evaluates to 2 if given more than 1 arg. Behavior is nasty and undefined if
* it's given more than 20 args.
*/
#define NUM_ARGS_CEIL2(...) \
NUM_ARGS_COUNTER(__VA_ARGS__, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 1)
Step 2:
#define _UNIMPLEMENTED1(msg) \
log("My creator has forsaken me. %s:%s:%d." msg, __FILE__, \
__func__, __LINE__)
#define _UNIMPLEMENTED2(msg, ...) \
log("My creator has forsaken me. %s:%s:%d." msg, __FILE__, \
__func__, __LINE__, __VA_ARGS__)
STEP 3:
#define UNIMPLEMENTED(...) \
CONCAT(_UNIMPLEMENTED, NUM_ARGS_CEIL2(__VA_ARGS__))(__VA_ARGS__)
Where CONCAT is implemented in the usual way. As a quick hint, if the above seems confusing: the goal of CONCAT there is to expand to another macro "call".
Note that NUM_ARGS itself isn't used. I just included it to illustrate the basic trick here. See Jens Gustedt's P99 blog for a nice treatment of it.
Two notes:
NUM_ARGS is limited in the number of arguments that it handles. Mine
can only handle up to 20, although the number is totally arbitrary.
NUM_ARGS, as shown, has a pitfall in that it returns 1 when given 0 arguments. The gist of it is that NUM_ARGS is technically counting [commas + 1], and not args. In this
particular case, it actually works to our
advantage. _UNIMPLEMENTED1 will handle an empty token just fine
and it saves us from having to write _UNIMPLEMENTED0. Gustedt has a
workaround for that as well, although I haven't used it and I'm not sure if it would work for what we're doing here.
If you are using gcc 8+, clang 6+ or MSVC 2019 (source), then you can also use the (newer) __VA_OPT__ macro, which conditionally expands if __VA_ARGS__ is non-empty.
So, we can convert the two FOO and BAR macros into one:
#define FOO(s, ...) printf(s __VA_OPT__(,) __VA_ARGS__)
and so, FOO("hello!") will expand to printf("hello!"), and FOO("x = %d", 5) will expand to printf("x = %d", 5).
This is a relatively new feature (introduced in C++2a) so your compiler might not support it yet.
This is the simplified version that I use. It is based upon the great techniques of the other answers here, so many props to them:
#define _SELECT(PREFIX,_5,_4,_3,_2,_1,SUFFIX,...) PREFIX ## _ ## SUFFIX
#define _BAR_1(fmt) printf(fmt "\n")
#define _BAR_N(fmt, ...) printf(fmt "\n", __VA_ARGS__);
#define BAR(...) _SELECT(_BAR,__VA_ARGS__,N,N,N,N,1)(__VA_ARGS__)
int main(int argc, char *argv[]) {
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
return 0;
}
That's it.
As with other solutions this is limited to the number of arguments the macro. To support more, add more parameters to _SELECT, and more N arguments. The argument names count down (instead of up) to serve as a reminder that the count-based SUFFIX argument is provided in reverse order.
This solution treats 0 arguments as though it is 1 argument. So BAR() nominally "works", because it expands to _SELECT(_BAR,,N,N,N,N,1)(), which expands to _BAR_1()(), which expands to printf("\n").
If you want, you can get creative with the use of _SELECT and provide different macros for different number of arguments. For example, here we have a LOG macro that takes a 'level' argument before the format. If format is missing, it logs "(no message)", if there is just 1 argument, it will log it through "%s", otherwise it will treat the format argument as a printf format string for the remaining arguments.
#define _LOG_1(lvl) printf("[%s] (no message)\n", #lvl)
#define _LOG_2(lvl,fmt) printf("[%s] %s\n", #lvl, fmt)
#define _LOG_N(lvl,fmt, ...) printf("[%s] " fmt "\n", #lvl, __VA_ARGS__)
#define LOG(...) _SELECT(_LOG,__VA_ARGS__,N,N,N,2,1)(__VA_ARGS__)
int main(int argc, char *argv[]) {
LOG(INFO);
LOG(DEBUG, "here is a log message");
LOG(WARN, "here is a log message with param: %d", 42);
return 0;
}
/* outputs:
[INFO] (no message)
[DEBUG] here is a log message
[WARN] here is a log message with param: 42
*/
if c++11 or above is available, and the macro is intended to be expanded to a function call, you can make a wrapper for it, for example:
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
can be converted to
#define BAR(fmt, ...) BAR_wrapper(fmt)(__VA_ARGS__)
where BAR_wrapper can be defined as:
struct BAR_wrapper_t {
BAR_wrapper_t(const char* fmt) : fmt(fmt) {}
const char* fmt;
int operator()() const { return printf(fmt); }
template <typename... Args>
int operator()(Args&& args) const { return printf(fmt, std::forward<Args>(args)...); }
};
inline BAR_wrapper_t BAR_wrapper(const char* fmt) { return BAR_wrapper_t(fmt); }
In your situation (at least 1 argument present, never 0), you can define BAR as BAR(...), use Jens Gustedt's HAS_COMMA(...) to detect a comma and then dispatch to BAR0(Fmt) or BAR1(Fmt,...) accordingly.
This:
#define HAS_COMMA(...) HAS_COMMA_16__(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0)
#define HAS_COMMA_16__(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define CAT_(X,Y) X##Y
#define CAT(X,Y) CAT_(X,Y)
#define BAR(.../*All*/) CAT(BAR,HAS_COMMA(__VA_ARGS__))(__VA_ARGS__)
#define BAR0(X) printf(X "\n")
#define BAR1(X,...) printf(X "\n",__VA_ARGS__)
#include <stdio.h>
int main()
{
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
}
compiles with -pedantic without a warning.
C (gcc), 762 bytes
#define EMPTYFIRST(x,...) A x (B)
#define A(x) x()
#define B() ,
#define EMPTY(...) C(EMPTYFIRST(__VA_ARGS__) SINGLE(__VA_ARGS__))
#define C(...) D(__VA_ARGS__)
#define D(x,...) __VA_ARGS__
#define SINGLE(...) E(__VA_ARGS__, B)
#define E(x,y,...) C(y(),)
#define NONEMPTY(...) F(EMPTY(__VA_ARGS__) D, B)
#define F(...) G(__VA_ARGS__)
#define G(x,y,...) y()
#define STRINGIFY(...) STRINGIFY2(__VA_ARGS__)
#define STRINGIFY2(...) #__VA_ARGS__
#define BAR(fmt, ...) printf(fmt "\n" NONEMPTY(__VA_ARGS__) __VA_ARGS__)
int main() {
puts(STRINGIFY(NONEMPTY()));
puts(STRINGIFY(NONEMPTY(1)));
puts(STRINGIFY(NONEMPTY(,2)));
puts(STRINGIFY(NONEMPTY(1,2)));
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
}
Try it online!
Assumes:
No arg contain comma or bracket
No arg contain A~G (can rename to hard_collide ones)
The standard solution is to use FOO instead of BAR. There are a few weird cases of argument reordering it probably can't do for you (though I bet someone can come up with clever hacks to disassemble and reassemble __VA_ARGS__ conditionally based on the number of arguments in it!) but in general using FOO "usually" just works.
When using va_start(), va_arg() and va_end() to read parameters passed to a method, is there a way to count how many arguments there are?
According to the man page if you call va_arg() too many times you get "random errors":
If there is no next argument, or if
type is not compatible with the type
of the actual next argument (as
promoted according to the default
argument promotions), random errors will occur.
No. a Variable Argument function (such as printf), must "know" when to stop looking for more arguments.
printf knows by the number of %d, %s and other symbols in its format string.
Other functions sometimes use Sentinel values:
sumValues(1, 3, 5, 7, 6, 9, -1); // will add numbers until it encounters a -1
Other functions may have the number of parameters stated up front:
AddNames(4, "Bill", "Alice", "Mike", "Tom");
Here is a fairly astonishing trick that allows you to build what you want using C99's variadic macros:
PP_NARG()
Returns the number of arguments contained in __VA_ARGS__
You can use this to write a macro wrapping your real function that adds a count to the front of the real function's arguments.
See also this question. However probably the classical approaches are still more sensible for a year or three yet!
The code, so that this answer is useful even without the Usenet archive...
/* The PP_NARG macro returns the number of arguments that have been
* passed to it.
*/
#define PP_NARG(...) \
PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
There are two ways to know how many arguments were passed. First, you can have one of the function parameters tell you (like printf for example). The other way is to have a sentinel value at the end of your list - for instance, you could stop at a NULL argument.
You can use va_copy if you choose the second method, but still want to count the parameters before deciding what to do with them.
A handy variation to the sentinel version of variadic functions is to define a macro that automagically adds up the expected sentinel as last argument :
#include <stdarg.h>
#include <assert.h>
int sum_(int unused, ...)
{
va_list args;
int sum, val;
va_start(args, unused);
sum = 0;
while ((val = va_arg(args, int)) != -1)
sum += val;
va_end(args);
return sum;
}
#define sum(...) sum_(41, ##__VA_ARGS__, -1)
void main(void)
{
assert(sum(1, 2, 3, 4, 5, 6) == 21);
}