va_arg, va_copy, va_end, va_start

Accède aux listes d'arguments variables.

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 
);  // (Pre-ANSI C89 standardization version)

Paramètres

  • type
    Type d'argument à récupérer.

  • arg_ptr
    Pointeur vers la liste d'arguments.

  • dest
    Pointeur à la liste d'arguments à initialiser à partir de src

  • src
    Pointeur à la liste initialisée d'arguments à copier à dest.

  • prev_param
    Paramètre qui précède le premier argument facultatif.

Valeur de retour

va_arg retourne l'argument actuel. va_copy, va_start et va_end ne retournent pas de valeurs.

Notes

Les macros va_arg, va_copy, va_end, et va_start fournissent un moyen portable d'accéder aux arguments d'une fonction lorsque la fonction accepte un nombre variable d'arguments. Il existe deux versions de macros : Les macros définies dans STDARG.H se conforment à la norme ISO C99 ; les macros définies dans VARARGS.H sont déconseillées mais sont conservées pour la compatibilité descendante avec un code qui a été écrit avant la norme ANSI C89.

Ces macros supposent que la fonction prend un nombre fixe d'arguments requis, suivi d'un nombre variable d'arguments facultatifs. Les arguments requis sont déclarés comme paramètres ordinaires à la fonction et sont accessibles via les noms de paramètres. Les arguments facultatifs sont accessibles via des macros dans STDARG.H (ou VARARGS.H pour un code qui a été écrit avant la norme ANSI C89), qui définit un pointeur vers le premier argument facultatif dans la liste d'arguments, récupère les arguments de la liste, puis réinitialise le pointeur quand le traitement de l'argument est terminé.

Les macros standard C, définies dans STDARG.H, sont utilisées comme suit :

  • va_start définit arg_ptr au premier argument facultatif dans la liste d'arguments passée à la fonction. L'argument arg_ptr doit avoir le type va_list. L'argument prev_param est le nom du paramètre requis qui précède immédiatement le premier argument facultatif dans la liste d'arguments. Si prev_param est déclaré avec une classe de registre de mémoire, le comportement de la macro n'est pas défini. va_start doit être utilisé avant que va_arg soit utilisé pour la première fois.

  • va_arg récupère une valeur de type depuis l'emplacement fourni par arg_ptr, et incrémente arg_ptr pour pointer vers l'argument suivant dans la liste avec la taille de type pour déterminer où l'argument suivant démarre. va_arg peut être utilisé plusieurs fois dans la fonction pour extraire des arguments de la liste.

  • va_copy effectue une copie d'une liste d'arguments dans son état actuel. Le paramètre src doit déjà être initialisé avec va_start; il peut avoir été mis à jour avec les appels de va_arg, mais ne doit pas avoir été réinitialisé avec va_end. L'argument suivant qui est récupéré par va_arg depuis dest est identique à l'argument suivant récupéré depuis src.

  • Une fois tous les arguments récupérés, va_end réinitialise le pointeur sur NULL. va_end doit être appelé à chaque liste d'arguments qui est initialisée avec va_start ou va_copy avant le retour de la fonction.

Remarque pour C++Remarque pour C++

Les macros dans VARARGS.H sont déconseillées et sont conservées uniquement pour la compatibilité descendante avec un code qui a été écrit avant la norme ANSI C89.Dans tous les autres cas, utilisez les macros dans STDARGS.H.

Lorsqu'ils sont compilés en utilisant /clr (Compilation pour le 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 natif et de type Common Langage Runtime (CLR). Considérez 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);
    }
}

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 attend que son deuxième paramètre soit un int ou un char*. Les arguments passés sont 0xffffffff ( un unsigned int, et non un int) et NULL (en réalité un int, et non un char*). Lorsque le programme est compilé pour le code natif, il produit cette sortie :

  
  

Toutefois, lorsque le programme est compilé à l'aide de /clr:pure, l'incompatibilité de type lui fait générer une exception. La solution consiste à utiliser des casts explicites :

int main()
{
   testit( 0, (int)0xFFFFFFFF ); // cast unsigned to int
   testit( 1, (char*)NULL );     // cast int to char*
}

Configuration requise

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;
}

Sortie

  

Équivalent .NET Framework

Classe de System::ParamArrayAttribute

Voir aussi

Référence

Accès à un argument

vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l