Condividi tramite


va_arg, va_copy, va_end, va_start

Accede a elenchi di argomenti variabile

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)

Parametri

  • type
    Tipo di argomento da recuperare.

  • arg_ptr
    Puntatore ad una lista di argomenti.

  • dest
    Puntatore all'elenco di argomenti da inizializzare da src

  • src
    Puntatore all'elenco degli argomenti inizializzati da copiare in dest.

  • prev_param
    Parametro che precede il primo argomento facoltativo.

Valore restituito

va_arg restituisce l'argomento corrente. va_copy, va_start e va_end non hanno valori di ritorno.

Note

Le macro va_arg, va_copy, va_end e va_start forniscono un modo portabile per accedere agli argomenti di una funzione quando la funzione accetta un numero variabile di argomenti. Esistono due versioni di macro: Le macro definite in STDARG.H conformi allo standard ISO C99; le macro definite in VARARGS.H sono deprecate ma vengono mantenute per garantire la compatibilità con codice scritto prima dello standard ANSI C89.

Queste macro presuppongono che la funzione accetti un numero fisso di argomenti obbligatori, seguito da un numero variabile di argomenti facoltativi. Gli argomenti necessari vengono dichiarati come parametri ordinari della funzione e possono essere acceduti con i nomi dei parametri. Gli argomenti opzionali sono accessibili tramite le macro in STDARG.H (o in VARARGS.H per il codice scritto prima dello standard ANSI C89), che impostano un puntatore al primo argomento facoltativo nell'elenco di argomenti, recupera gli argomenti dall'elenco e reimposta il puntatore quando l'elaborazione dell'argomento è stata completata.

Le macro standard C, definite in STDARG.H, sono utilizzate nel modo seguente:

  • va_start imposta arg_ptr al primo argomento facoltativo nell'elenco degli argomenti che sono passati alla funzione. L'argomento arg_ptr deve avere il tipo va_list. L'argomento prev_param è il nome del parametro obbligatorio che precede immediatamente il primo argomento facoltativo nell'elenco degli argomenti. Se prev_param viene dichiarata con la classe di archiviazione registro, il comportamento della macro è indefinito. va_start deve essere utilizzata prima che va_arg venga utilizzata per la prima volta.

  • va_arg recupera un valore di type dalla posizione fornita da arg_ptr e incrementa arg_ptr per puntare all'argomento seguente dell'elenco, utilizzando la dimensione di type per determinare dove l'argomento seguente inizia. va_arg può essere utilizzata un numero di volte qualsiasi nella funzione che recupera gli argomenti dall'elenco.

  • va_copy crea una copia di un elenco di argomenti nello stato corrente. Il parametro src deve essere già inizializzato con va_start; può essere aggiornato con chiamate va_arg, ma non deve essere reimpostato con va_end. L'argomento seguente recuperato da va_arg da dest equivale all'argomento successivo recuperato da src.

  • Dopo che tutti gli argomenti vengono recuperati, viene reimpostato il puntatore va_end a NULL. va_end deve essere chiamato in ogni elenco di argomenti inizializzati con va_start o va_copy prima che la funzione ritorni.

Nota di C++Nota di C++

Le macro in VARARGS.H sono deprecate e vengono mantenute solo per la compatibilità con versioni precedenti di codice scritto nello standard ANSI C89.In tutti gli altri casi, utilizzare le macro in STDARGS.H.

Quando vengono compilate utilizzando /clr (Compilazione Common Language Runtime), i programmi che utilizzano queste macro possono generare risultati imprevisti a causa delle differenze tra il tipo di sistema nativo e il sistema Common Language Runtime (CLR). Considerare questo programma:

#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*
}

Si noti che testit richiede al secondo parametro sia un int oppure un char*. Gli argomenti passati sono 0xffffffff ( un unsigned int, non un int) e NULL ( in realtà un int, non un char*). Quando il programma viene compilato in codice nativo, genera questo output:

  
  

Tuttavia, quando il programma viene compilato tramite /clr:pure, a causa dei tipi non corrispondenti può generare un'eccezione. La soluzione consiste nell'utilizzare i cast espliciti:

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

Requisiti

Intestazione: <stdio.h> and <stdarg.h>

Intestazione deprecata: <varargs.h>

Librerie

Tutte le versioni delle Librerie di runtime C.

Esempio

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

Output

  

Equivalente .NET Framework

System::ParamArrayAttribute Class

Vedere anche

Riferimenti

Accesso agli argomenti

vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l