I'm kinda confused with the usage of <stdarg.h>
features. I can't figure out how to properly pass a va_list
to the argument function. Here's a simplified example of what I'm trying to achive:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void caller(int (*func)(size_t, ...), size_t n_args, ...) {
va_list args;
va_start(args, n_args);
va_list args_for_func;
va_copy(args_for_func, args);
printf("(");
for (size_t i = 0; i < n_args-1; i++) {
printf("%i, ", va_arg(args, int));
}
printf("%i) => ", va_arg(args, int));
int result = func(n_args, args_for_func);
va_end(args_for_func);
printf("%i", result);
va_end(args);
}
int sum(size_t n_args, ...) {
va_list args;
va_start(args, n_args);
int result = 0;
for (size_t i = 0; i < n_args; i++) {
result += va_arg(args, int);
}
va_end(args);
return result;
}
int main() {
// expected: (1, 2, 3, 4, 5) => 15
// got: (1, 2, 3, 4, 5) => gibberish
caller(sum, 5llu, 1, 2, 3, 4, 5);
}
A function can only process its variadic parameters using a va_list
, and the parameters referenced by the va_list
cannot be expanded out in a call to another variadic function. However, the va_list
value can be passed by value to another function, so the way to solve the problem is to change the function pointer to point to a function that uses a va_list
:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void caller(int (*func)(size_t, va_list), size_t n_args, ...) {
va_list args;
va_start(args, n_args);
va_list args_for_func;
va_copy(args_for_func, args);
printf("(");
for (size_t i = 0; i < n_args-1; i++) {
printf("%i, ", va_arg(args, int));
}
printf("%i) => ", va_arg(args, int));
int result = func(n_args, args_for_func);
va_end(args_for_func);
printf("%i", result);
va_end(args);
}
int vsum(size_t n_args, va_list args) {
int result = 0;
for (size_t i = 0; i < n_args; i++) {
result += va_arg(args, int);
}
return result;
}
int sum(size_t n_args, ...) {
va_list args;
va_start(args, n_args);
int result = vsum(n_args, args);
va_end(args);
return result;
}
int main() {
caller(vsum, 5llu, 1, 2, 3, 4, 5);
}