va_arg, va_copy, va_end, va_start
Listy uzyskuje dostęp do zmiennej argument.
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)
Parametry
type
Typ argumentu do pobrania.arg_ptr
Wskaźnik na listę argumentów.dest
Wskaźnik do listy argumentów zainicjowana zsrcsrc
Wskaźnik, aby zainicjować listę argumentów, aby skopiować do dest.prev_param
Parametr, który poprzedza pierwszy argument opcjonalny.
Wartość zwracana
va_argZwraca bieżący argument.va_copy, va_start i va_end nie zwraca wartości.
Uwagi
va_arg, va_copy, va_end, I va_start makra zapewniają przenośne sposób uzyskać dostęp do argumentów do funkcji, gdy funkcja przyjmuje zmiennej liczbie argumentów.Dostępne są dwie wersje makr: makra zdefiniowane w STDARG.H odpowiadają C99 ISO standardowych; makra zdefiniowane w VARARGS.H są przestarzałe, ale są zachowywane dla zgodności z poprzednimi wersjami z kodem, który został napisany przed standardowych kompilatorem C89 ANSI.
Te makra założono, że funkcja przyjmuje stałą liczbę wymaganych argumentów, następuje zmienna liczba argumentów opcjonalnych.Wymagane argumenty są deklarowane jako zwykłe parametry funkcji i mogą być udostępniane za pośrednictwem nazwy parametrów.Opcjonalne argumenty są dostępne za pośrednictwem makra w STDARG.H (lub VARARGS.H dla kodu, który został napisany przed standardu ANSI kompilatorem C89), który ustawia wskaźnik do pierwszego argumentu opcjonalne na liście argumentów pobiera argumenty z listy, a po zakończeniu przetwarzania argument resetuje wskaźnik.
C standardowe makra, określonych w STDARG.H, są używane w następujący sposób:
va_startUstawia arg_ptr do pierwszego argumentu opcjonalne na liście argumentów przekazanych do funkcji.Argument arg_ptr musi być va_list typu.Argument prev_param jest nazwą wymagany parametr, który bezpośrednio na liście argumentów poprzedza pierwszy argument opcjonalny.Jeśli prev_param jest zadeklarowana za pomocą klasy magazynu rejestru, zachowanie makro jest niezdefiniowane.va_startmuszą być używane przed va_arg jest używany po raz pierwszy.
va_argpobiera wartość type z lokalizacji, w której wyraża się przez arg_ptroraz przyrostów, arg_ptr wskaż polecenie Następny argument na liście przy użyciu rozmiaru type do określenia, gdzie zaczyna się następny argument.va_argmoże być używana dowolną liczbę razy w funkcji do pobierania argumentów z listy.
va_copyTworzy kopię listy argumentów w jego bieżącym stanie.src Parametr musi być już zainicjowany z va_start; został zaktualizowany z va_arg wywołuje, ale musi być nie Resetuj z va_end.Następny argument, że pobrana przez va_arg z dest jest taka sama jak dalej argument, który jest pobierany z src.
Po pobraniu wszystkich argumentów va_end resetuje wskaźnik, aby wartości NULL.va_endmusi być wywołany w każdej listy argumentów, który jest inicjowany z va_start lub va_copy zanim funkcja zwraca.
Uwaga dotycząca języka C++ |
---|
Makra w VARARGS.H są przestarzałe i są zachowywane tylko dla wstecznej zgodności z kodem, który został napisany przed standardu ANSI kompilatorem C89.We wszystkich innych przypadkach należy użyć makra z STDARGS.H. |
Kiedy są kompilowane za pomocą /clr (Kompilacja środowiska uruchomieniowego języka wspólnego), programy korzystające z tych makr może generować nieoczekiwane rezultaty, ze względu na różnice między macierzystym i wspólnego języka wspólnego (CLR) typu systemów.Należy wziąć pod uwagę ten program:
#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*
}
Należy zauważyć, że testit oczekuje, że drugi parametr może przyjąć formę int lub char*.Argumenty przekazywane są 0xffffffff ( unsigned int, nie int) i NULL (faktycznie int, nie char*).Gdy program jest kompilowany do kodu macierzystego, daje to wyjście:
Jednakże, kiedy program jest kompilowana za pomocą /clr:pure, niezgodności typu spowodować wygenerowanie wyjątku.Rozwiązaniem jest użycie jawne poświaty:
int main()
{
testit( 0, (int)0xFFFFFFFF ); // cast unsigned to int
testit( 1, (char*)NULL ); // cast int to char*
}
Wymagania
Nagłówek:<stdio.h> i <stdarg.h >
Niezalecane nagłówek:<varargs.h>
Biblioteki
Wszystkie wersje Bibliotek uruchomieniowych C.
Przykład
// 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;
}
Dane wyjściowe
Odpowiednik w programie .NET Framework
Klasa System::ParamArrayAttribute