Probleme:
Comment en C standard (C99) "simuler" le comportement des fonctions avec argument par defaut du C++ ?
int f(int x=2, int y=3, int z=4, int t=5);
?
spectras :Le C99 autorise la surcharge de fonctions ?
En faisant une fonction pour chaque nombre de paramètres ?
int f() {return f(2, 3, 4, 5);}
int f(int x) {return f(x, 3, 4, 5);}
int f(int x, int y) {return f(x, y, 4, 5);}
....
int f(int x, int y, int z, int t);
#include <stdio.h> #include <stdarg.h> #define MAGIC 424242 void f1(int plop,...){ int args[3] = {42,51,1664}; /* default values */ va_list ap; va_start(ap, plop); for(int i = 0;i < 3;i++){ int tmp = va_arg(ap,int); if(tmp == MAGIC) break; else args[i] = tmp; } va_end(ap); for(int i = 0;i < 3;i++){ printf("%d ",args[i]); } printf("\n"); } #define f(...) f1(42, ##__VA_ARGS__ , MAGIC ) int main(int argc, char *argv[]) { f(1); f(1,2); f(1,2,3); }
#include <stdio.h> #include <stdarg.h> void f1(int plop,...){ int args[3] = {50,51,52}; int rd_args[7]; int nb_rd_args = 0; va_list ap; va_start(ap, plop); for(int i = 0;i < 7;i++){ rd_args[i] = va_arg(ap,int); if(i > 3 && rd_args[i] == 0 && rd_args[i-1] == 42 && rd_args[i-2] == 42 && rd_args[i-3] == 42) { nb_rd_args = i - 3; break; } } va_end(ap); for(int i = 0;i < nb_rd_args;i++) args[i] = rd_args[i]; for(int i = 0;i < 3;i++){ printf("%d ",args[i]); } printf("\n"); } #define f(...) f1(42 , ##__VA_ARGS__ , 42, 42, 42, 0) int main(int argc, char *argv[]) { f(10); f(10,11); f(10,11,12); }
This is a special feature of the GNU C preprocessor: `##' before a rest argument that is empty discards the preceding sequence of non-whitespace characters from the macro definition.
Et à l'usage ça ressemble à ça #define eprintf(format, args...) \ fprint
BookeldOr :
nope c'est pas GCC, c'est du c99, il faut mettre ##__VA_ARGS__ mais ça ne marche pas si les seuls arguments de la macro sont ceux de l'ellipse, il faut un premier argument pour que ça fonctionne.
spectras :
f (stderr, format , ## args)Et à l'usage ça ressemble à ça #define eprintf(format, args...) \ fprint
note l'espace entre format et la virgule qui suit (sinon format sera dégagé en même temps que la virgule), ansi que l'espace entre ## et args (sinon ça serait pris comme de la concaténation de tokens)
#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,N,...) N #define PP_RSEQ_N() 9,8,7,6,5,4,3,2,1,0
PP_NARG(A) -> 1 PP_NARG(A,B) -> 2 PP_NARG(A,B,C) -> 3 PP_NARG(A,B,C,D) -> 4 PP_NARG(A,B,C,D,E) -> 5
int f(int, int, int, int); #define f(...) select_4(__VA_ARGS__, f(__VA_ARGS__),f(__VA_ARGS__,5),f(__VA_ARGS__,4,5),f(__VA_ARGS__,3,4,5),f(2,3,4,5)) #define select_4(_1,_2,_3,_4,N,...) N
int (*func) (int, int, int, int); func = f; f (17,42); f(17);
int (*func) (int, int, int, int); func = f; f (17,42,4,5); f(17,3,4,5);
f();
#define new_f(...) new_f2((__VA_ARGS__)) #define new_f2(parms) (#parms[2] ? ...valeur par défaut... : old_f parms)