Variadic Functions in C
A Nicer Approach
So I've described the problem, and even why it maybe makes sense for that problem to exist at the low level of the language definition, but we can do better for actual humans writing C.
As of C99, we have variadic macros, and we have compound literals. This means that we can wrap variadic functions in macros that automate two common conventions for variadic functions:
pass a magic end-of-arguments value, or
pass the number of variadic parameters.
Let's take a function like `execl` for example: it takes some number of `char *`, and it expects the last one to be a null pointer. Behold:
#define EXECL(...) execl(__VA_ARGS__, (char * )0)
Boom. Problem solved. No more segfaults or stack corruptions or exploitable code execution vulnerabilities in your code just because you forgot to put a null pointer at the end, or forgot to cast it to the a pointer type with a compatible representation.
Now how do you count arguments? Well, if your arguments are all of the same type, or implicitly convertible to the same type, you can throw them into a compound literal for an array of that type and take the size of that array:
#define ARGUMENT_COUNT(type, ...) (sizeof((type[]){__VA_ARGS__}) / sizeof(type))
So then if you have a function like this:
int sum(size_t argument_count, ...)
You can wrap it like this:
#define SUM(...) sum(ARGUMENT_COUNT(int, __VA_ARGS__), __VA_ARGS__)
Same benefit: the function receives an automatically computed-at-compile-time first argument of how many parameters the wrapper macro call received. And since the stuff inside a `sizeof` operator is not evaluated - only the type of the expression is statically figured out per compile-time C rules - you don't get any of the problems with macros evaluating their arguments multiple times.










