You can take a look to NARGS macro
Adapted to your code:
#include <stdio.h>
#include <stdarg.h>
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define print(...) fnprint(NARGS(__VA_ARGS__), __VA_ARGS__)
void fnprint(int n, ...)
{
va_list ap;
int num;
va_start(ap, n);
while (n--) {
num = va_arg(ap, int);
printf("%d\n", num);
}
va_end(ap);
return;
}
int main(void)
{
print(1, 2, 3, 4, 5);
return 0;
}
EDIT: If you want to use the same name for macro and function, use () to stop the preprocessor from expanding the function definition:
#define print(...) print(NARGS(__VA_ARGS__), __VA_ARGS__)
void (print)(int n, ...) /* Note () around the function name */
{
...
EDIT 2: Another (ugly) method (but without restriction in the number of args) using compound literals (std 99) and sizeof
:
#include <stdio.h>
#include <stdarg.h>
#define print(...) print(sizeof((int []) {__VA_ARGS__}) / sizeof(int), __VA_ARGS__)
void (print)(int n, ...)
{
va_list ap;
int num;
va_start(ap, n);
while (n--) {
num = va_arg(ap, int);
printf("%d\n", num);
}
va_end(ap);
return;
}
int main(void)
{
print(1, 2, 3, 4, 5);
return 0;
}
print
is expanded to:
print(sizeof((int []) {1, 2, 3, 4, 5}) / sizeof(int), 1, 2, 3, 4, 5);
But constructions like print(1, 2, 3, a_var++, 4, 5);
or print(1, 2, some_func_returning_int(), 4, 5);
evaluates a_var++
and some_func_returning_int()
two times, thats a big problem.