va_arg, va_copy, va_end, va_start

Accede a elenchi di argomenti variabili.

Sintassi

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)

Parametri

type
Tipo di argomento da recuperare.

arg_ptr
Puntatore all'elenco di argomenti.

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

src
Puntatore all'elenco inizializzato di argomenti da copiare in dest.

prev_param
Parametro che precede il primo argomento facoltativo.

Valore restituito

va_arg restituisce l'argomento corrente. va_copye va_startva_end non restituiscono valori.

Osservazioni:

Le macro va_arg, va_copy, va_end e va_start offrono un modo portabile per accedere agli argomenti di una funzione quando la funzione accetta un numero variabile di argomenti. Esistono due versioni delle macro: le macro definite in STDARG.H sono conformi allo standard ISO C99. Le macro definite in VARARGS.H sono deprecate, ma vengono mantenute per garantire la compatibilità con le versioni precedenti con il 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 obbligatori vengono dichiarati come parametri comuni per la funzione e sono accessibili tramite i nomi dei parametri. Gli argomenti facoltativi sono accessibili tramite le macro in STDARG.H (o VARARGS.H per il codice scritto prima dello standard ANSI C89), che imposta un puntatore al primo argomento facoltativo nell'elenco di argomenti, recupera gli argomenti dall'elenco e reimposta il puntatore al termine dell'elaborazione dell'argomento.

Le macro standard C, definite in STDARG.H, vengono usate come segue:

  • va_start imposta arg_ptr sul primo argomento facoltativo nell'elenco di argomenti passati alla funzione. L'argomento arg_ptr deve essere di tipo va_list. L'argomento prev_param è il nome del parametro obbligatorio che precede il primo argomento facoltativo nell'elenco di argomenti. Se prev_param viene dichiarata con la classe di archiviazione nel registro, il comportamento della macro non è definito. È necessario usare va_start prima di usare va_arg per la prima volta.

  • va_arg recupera un valore di type dal percorso specificato da arg_ptr e incrementa arg_ptr in modo che punti all'argomento successivo nell'elenco usando le dimensioni di type per determinare dove inizia l'argomento successivo. È possibile usare va_arg un qualsiasi numero di volte nella funzione per recuperare gli argomenti dall'elenco.

  • va_copy crea una copia di un elenco di argomenti nello stato corrente. Il parametro src deve essere già stato inizializzato con va_start. Potrebbe essere stato aggiornato con chiamate a va_arg, ma non deve essere stato reimpostato con va_end. L'argomento successivo che viene recuperato da va_arg da dest corrisponde all'argomento successivo recuperato da src.

  • Dopo aver recuperato tutti gli argomenti, va_end reimposta il puntatore su NULL. È necessario chiamare va_end per ogni elenco di argomenti inizializzato con va_start o va_copy prima che la funzione restituisca il controllo.

Nota

Le macro in VARARGS.H sono deprecate e vengono mantenute solo per garantire la compatibilità con il codice scritto prima dello standard ANSI C89. In tutti gli altri casi, usare le macro in STDARGS.H.

Quando vengono compilati tramite /clr (Compilazione Common Language Runtime), i programmi che usano queste macro possono generare risultati imprevisti a causa delle differenze tra sistemi di tipi nativi e CLR (Common Language Runtime). Si consideri 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);
    }

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

Notare che testit si aspetta che il secondo parametro sia int o char*. Gli argomenti passati sono 0xffffffff (unsigned int, non int) e NULL (in effetti int e non char*). Quando il programma viene compilato per il codice nativo, produce il seguente output:

-1

(null)

Requisiti

Intestazione:<stdio.h> e <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;
}
Deviation is: 0.816497
Deviation is: 2.236068
Deviation is: 0.000000

Vedi anche

Accesso agli argomenti
vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l