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_copy
e va_start
va_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
impostaarg_ptr
sul primo argomento facoltativo nell'elenco di argomenti passati alla funzione. L'argomentoarg_ptr
deve essere di tipova_list
. L'argomentoprev_param
è il nome del parametro obbligatorio che precede il primo argomento facoltativo nell'elenco di argomenti. Seprev_param
viene dichiarata con la classe di archiviazione nel registro, il comportamento della macro non è definito. È necessario usareva_start
prima di usareva_arg
per la prima volta.va_arg
recupera un valore ditype
dal percorso specificato daarg_ptr
e incrementaarg_ptr
in modo che punti all'argomento successivo nell'elenco usando le dimensioni ditype
per determinare dove inizia l'argomento successivo. È possibile usareva_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 parametrosrc
deve essere già stato inizializzato conva_start
. Potrebbe essere stato aggiornato con chiamate ava_arg
, ma non deve essere stato reimpostato conva_end
. L'argomento successivo che viene recuperato dava_arg
dadest
corrisponde all'argomento successivo recuperato dasrc
.Dopo aver recuperato tutti gli argomenti,
va_end
reimposta il puntatore suNULL
. È necessario chiamareva_end
per ogni elenco di argomenti inizializzato conva_start
ova_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