Другая возможность - использовать varargs.В следующем примере каждая вызываемая функция выполняет свою собственную интерпретацию параметров.
#include <stdio.h>
#include <stdarg.h>
// expects 4 arguments (int, int, int, char*)
void f1(va_list args) {
int a, b, c;
char *d;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, int);
d = va_arg(args, char *);
printf("%d, %d, %d: %s\n", a, b, c, d);
}
// expects 3 ars (int, int, char*);
void f2(va_list args) {
int a, b;
char *c;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, char *);
printf("%d, %d: %s\n", a, b, c);
}
void caller(void (*f)(va_list), ...) {
va_list args;
va_start(args, f);
f(args);
}
int main() {
caller(&f1, 0, 1, 3, "hello");
caller(&f2, 1, 2, "bye");
return 0;
}
Другая возможность состоит в том, чтобы иметь caller
для интерпретации параметров на основе некоторой информации о типе и вызова правильного вызова функции.Это может быть полезно, если у вас ограниченное количество шаблонов аргументов и просто обычные функции для вызова:
void f3(int a, int b, int c, char *d) {
printf("%d, %d, %d: %s\n", a, b, c, d);
}
void f4(int a, int b, char *c) {
printf("%d, %d: %s\n", a, b, c);
}
typedef enum {
type1, type2
} Types;
void caller1(Types t, void (*f)(), ...) {
va_list args;
va_start(args, f);
switch (t) {
case type1: {
int a, b, c;
char *d;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, int);
d = va_arg(args, char *);
f(a,b,c,d);
break;
}
case type2: {
int a, b;
char *c;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, char *);
f(a,b,c);
}
}
}
int main() {
caller1(type1, &f3, 3,2,1, "hi");
caller1(type2, &f4, 3,2,"take care");
return 0;