void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
La fonction appelée doit déclarer un objet de type va_list utilisé par les macros va_start(), va_arg() et va_end().
Le paramètre last est le nom du dernier paramètre avant la liste d'argument variable, c'est-à-dire le dernier paramètre dont la fonction connaisse le type.
Comme l'adresse de ce paramètre est utilisée dans la macro va_start(), il ne doit pas être déclaré comme une variable en registre, ni comme un type fonction ou tableau.
La première utilisation de la macro va_arg() après celle de va_start() renvoie l'argument suivant last. Les invocations successives renvoient les valeurs des arguments restants.
S'il n'y a pas d'argument suivant, ou si type n'est pas compatible avec le type réel du prochain argument, des erreurs imprévisibles se produiront.
Si ap est passé à une fonction qui utilise va_arg(ap,type) alors la valeur de ap est indéfinie après le retour de cette fonction.
va_list aq = ap;Malheureusement, il y a aussi des systèmes qui créent une table de pointeurs (de longueur 1), et on devrait écrire
va_list aq; *aq = *ap;De plus, sur les systèmes où les paramètres sont passés dans des registres, il peut être nécessaire pour va_start() d'allouer de la mémoire, d'y enregistrer les paramètres ainsi que l'indication du paramètre suivant, afin que va_arg() puisse balayer la liste. Ainsi va_end() pourra libérer la mémoire allouée. Pour gérer ces situations, C99 ajoute une macro va_copy(), afin que les affectations ci-dessus soient remplacées par
va_list aq; va_copy(aq, ap); ... va_end(aq);À chaque invocation de va_copy() doit correspondre une invocation de va_end() dans la même fonction. Certains systèmes qui ne disposent pas de va_copy() ont une macro __va_copy() à la place, puisque c'était le nom proposé auparavant.
La mise en oeuvre historique est :
#include <varargs.h> void foo(va_alist) va_dcl { va_list ap; va_start(ap); while (...) { ... x = va_arg(ap, type); ... } va_end(ap); }Sur certains systèmes, va_end() contient une accolade fermante « } » correspondant à l'accolade ouvrante « { » dans va_start(), ainsi les deux macros doivent se trouver dans la même fonction, placées d'une manière qui permette ceci.
#include <stdio.h> #include <stdarg.h> void foo(char *fmt, ...) { va_list ap; int d; char c, *s; va_start(ap, fmt); while (*fmt) switch (*fmt ++) { case aqsaq: /* chaîne */ s = va_arg (ap, char *); printf("chaîne %s\n", s); break; case aqdaq: /* entier */ d = va_arg (ap, int); printf("int %d\n", d); break; case aqcaq: /* caractère */ /* need a cast here since va_arg only takes fully promoted types */ c = va_arg (ap, char); printf("char %c\n", c); break; } va_end(ap); }
Ce document est une traduction réalisée par Christophe Blaess <http://www.blaess.fr/christophe/> le 7 novembre 1996 et révisée le 17 juillet 2008.
L'équipe de traduction a fait le maximum pour réaliser une adaptation française de qualité. La version anglaise la plus à jour de ce document est toujours consultable via la commande : « LANG=C man 3 stdarg ». N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute erreur dans cette page de manuel.
Dernière mise à jour : 17 juillet 2008