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 srcsrc
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++ |
---|
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