va_arg
, , va_copy
va_end
, ,va_start
Accède à des listes d’arguments variables.
Syntaxe
type va_arg(
va_list arg_ptr,
type
);
void va_copy(
va_list dest,
va_list src
); // (ISO C99 and later)
void va_end(
va_list arg_ptr
);
void va_start(
va_list arg_ptr,
prev_param
); // (ANSI C89 and later)
void va_start(
arg_ptr
); // (deprecated Pre-ANSI C89 standardization version)
Paramètres
type
Type d’argument à récupérer.
arg_ptr
Pointeur désignant la liste d’arguments.
dest
Pointeur désignant la liste d’arguments à initialiser à partir de src
.
src
Pointeur désignant la liste d’arguments initialisée à copier dans dest
.
prev_param
Paramètre qui précède le premier argument facultatif.
Valeur retournée
va_arg
retourne l’argument actif. va_copy
et va_start
va_end
ne retournez pas de valeurs.
Notes
Les macros va_arg
, va_copy
, va_end
et va_start
offrent un moyen portable d’accéder aux arguments pour une fonction qui accepte un nombre variable d’arguments. Il existe deux versions des macros : les macros définies conformément STDARG.H
à la norme ISO C99 ; les macros définies dans VARARGS.H
sont déconseillées, mais sont conservées pour la compatibilité descendante avec le code écrit avant la norme ANSI C89.
Ces macros considèrent que la fonction accepte un nombre fixe d’arguments obligatoires, suivi d’un nombre variable d’arguments facultatifs. Les arguments obligatoires sont déclarés à la fonction en tant que paramètres ordinaires et sont accessibles via les noms des paramètres. Les arguments facultatifs sont accessibles via les macros dans STDARG.H
(ou VARARGS.H
pour le code écrit avant la norme ANSI C89), qui définit un pointeur sur le premier argument facultatif dans la liste d’arguments, récupère les arguments de la liste et réinitialise le pointeur lorsque le traitement des arguments est terminé.
Les macros standard C, définies dans STDARG.H
, sont utilisées comme suit :
va_start
définitarg_ptr
comme étant le premier argument facultatif de la liste d’arguments à être passé à la fonction. L’argumentarg_ptr
doit être de typeva_list
. L’argumentprev_param
est le nom du paramètre obligatoire qui précède immédiatement le premier argument facultatif dans la liste d’arguments. Siprev_param
est déclarée avec la classe de stockage register, le comportement de la macro est indéfini.va_start
doit être utilisée avant la première utilisation deva_arg
.va_arg
récupère une valeur detype
à partir de l’emplacement indiqué pararg_ptr
et incrémentearg_ptr
pour pointer vers le prochain argument de la liste en utilisant la taille detype
pour déterminer le point de départ du prochain argument.va_arg
peut être utilisé autant de fois que nécessaire dans la fonction pour récupérer les arguments de la liste.va_copy
crée une copie d’une liste d’arguments dans son état actuel. Le paramètresrc
doit déjà être initialisé avecva_start
; il peut avoir été mis à jour avec des appelsva_arg
, mais il ne doit pas avoir été réinitialisé avecva_end
. Le prochain argument à être récupéré parva_arg
à partir dedest
est le même que celui qui est récupéré à partir desrc
.Une fois tous les arguments récupérés,
va_end
réinitialise le pointeur surNULL
.va_end
doit être appelé pour chaque liste d’arguments qui est initialisée avecva_start
ouva_copy
avant le retour de la fonction.
Remarque
Les macros contenues dans VARARGS.H sont obsolètes et sont conservées uniquement pour assurer une compatibilité descendante avec le code qui a été écrit avant la norme ANSI C89. Dans tous les autres cas, utilisez les macros contenues dans STDARGS.H.
Lorsqu’elles sont compilées à l’aide /clr
de (compilation Common Language Runtime), les programmes qui utilisent ces macros peuvent générer des résultats inattendus en raison de différences entre les systèmes de type CLR (Native Language Runtime). Prenons l’exemple de ce programme :
#include <stdio.h>
#include <stdarg.h>
void testit (int i, ...)
{
va_list argptr;
va_start(argptr, i);
if (i == 0)
{
int n = va_arg(argptr, int);
printf("%d\n", n);
}
else
{
char *s = va_arg(argptr, char*);
printf("%s\n", s);
}
va_end(argptr);
}
int main()
{
testit(0, 0xFFFFFFFF); // 1st problem: 0xffffffff is not an int
testit(1, NULL); // 2nd problem: NULL is not a char*
}
Notez que testit
s’attend à ce que son deuxième paramètre soit un int
ou un char*
. Les arguments transmis sont 0xffffffff (un unsigned int
, et non un int
) et NULL
(en réalité un int
, et non un char*
). Quand le programme est compilé pour du code natif, il génère cette sortie :
-1
(null)
Spécifications
En-tête : <stdio.h>
et <stdarg.h>
En-tête déconseillé : <varargs.h>
Bibliothèques
Toutes les versions des bibliothèques Runtime C.
Exemple
// crt_va.c
// Compile with: cl /W3 /Tc crt_va.c
// The program below illustrates passing a variable
// number of arguments using the following macros:
// va_start va_arg va_copy
// va_end va_list
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
double deviation(int first, ...);
int main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf("Deviation is: %f\n", deviation(2, 3, 4, -1 ));
/* Call with 4 integers. */
printf("Deviation is: %f\n", deviation(5, 7, 9, 11, -1));
/* Call with just -1 terminator. */
printf("Deviation is: %f\n", deviation(-1));
}
/* Returns the standard deviation of a variable list of integers. */
double deviation(int first, ...)
{
int count = 0, i = first;
double mean = 0.0, sum = 0.0;
va_list marker;
va_list copy;
va_start(marker, first); /* Initialize variable arguments. */
va_copy(copy, marker); /* Copy list for the second pass */
while (i != -1)
{
sum += i;
count++;
i = va_arg(marker, int);
}
va_end(marker); /* Reset variable argument list. */
mean = sum ? (sum / count) : 0.0;
i = first; /* reset to calculate deviation */
sum = 0.0;
while (i != -1)
{
sum += (i - mean)*(i - mean);
i = va_arg(copy, int);
}
va_end(copy); /* Reset copy of argument list. */
return count ? sqrt(sum / count) : 0.0;
}
Deviation is: 0.816497
Deviation is: 2.236068
Deviation is: 0.000000
Voir aussi
Accès aux arguments
vfprintf
, , _vfprintf_l
vfwprintf
, ,_vfwprintf_l