Provided by: manpages-pl-dev_0.6-2_all 

NAZWA
stdarg, va_start, va_arg, va_end, va_copy - listy zmiennych argumentów
SKŁADNIA
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
OPIS
Funkcję można wołać z różną liczbą argumentów różnych typów. Plik nagłówkowy <stdarg.h> deklaruje typ
va_list i definiuje trzy makra, iterujące przez listę argumentów, których liczba i typy nie są znane
wywołanej funkcji.
Wywołana funkcja musi zadeklarować obiekt typu va_list, który jest używany przez makra va_start(),
va_arg() i va_end().
va_start()
Makro va_start() inicjuje ap do dalszego użytku przez va_arg() i va_end() i musi być wywołane pierwsze.
Parametr last jest nazwą ostatniego argumentu przed zmienną listą argumentów, czyli ostatnim argumentem,
którego typ jest funkcji znany.
Ponieważ adres tego parametru jest używany w makrze va_start(), nie powinien być deklarowany jako zmienna
rejestrowa, funkcja czy typ tablicowy.
va_arg()
Makro va_arg() rozwija się do wyrażenia, które ma typ i wartość następnego argumentu w wywołaniu.
Argument ap to ap z va_list() zainicjowany przez va_start(). Każde wywołanie va_arg() zmienia ap tak, że
następne wywołanie zwraca następny argument. Argument type jest nazwą typu, podaną tak że typ wskaźnika
do obiektu, który ma podany typ, można uzyskać przez dodanie * do type.
Pierwsze użycie makra va_arg() po va_start() zwraca argument za last (ostatnim). Kolejne wywołania
zwracają wartości pozostałych argumentów.
Jeśli nie ma następnego argumentu lub jeśli type nie jest zgodny z rzeczywistym typem następnego
argumentu, pojawią się losowe błędy.
Jeśli ap zostanie przekazane do funkcji używającej va_arg(ap,type), to wartość ap po zakończeniu tej
funkcji będzie nieokreślona.
va_end()
Każdemu wywołaniu va_start() musi odpowiadać wywołanie va_end() w obrębie tej samej funkcji. Po wywołaniu
va_end() wartość ap będzie nieokreślona. Lista może być przetwarzana wielokrotnie, przy czym każde
przetworzenie musi być zawarte pomiędzy va_start() a va_end(). va_end() może być zarówno makrem, jak i
funkcją.
va_copy()
Makro va_copy() kopiuje (poprzednio zainicjowaną) listę src argumentów o zmiennej długości do dest.
Zachowanie to jest takie samo, jakby va_start() zostało zaaplikowane do dest z tym samym argumentem last,
po którym następowałaby ta sama liczba wywołań va_arg(), która była użyta do tej pory, aby osiągnąć
bieżący stan zmiennej src.
Oczywista implementacja zawierałaby wskaźnik va_list do ramki stosu funkcji o zmiennej liczbie
argumentów. Przy takiej konfiguracji (jak dotąd, najpowszechniejszej) nie ma żadnych przeciwwskazań do
podstawienia
va_list aq = ap;
Niestety, są również systemy, które robią to poprzez tablicę wskaźników (o długości 1) i wtedy niezbędne
jest
va_list aq;
*aq = *ap;
Wreszcie, w systemach, które przekazują parametry w rejestrach, może okazać się konieczne przydzielenie
pamięci przez va_start(), przechowanie tam argumentów, jak też wskazań, który argument jest następny, tak
aby va_arg() mogło przejść całą listę. Wówczas va_end() może wreszcie zwolnić przydzieloną w tym celu
pamięć. Aby dostosować się do tej sytuacji, C99 dodaje makro va_copy(), tak aby powyższe przypisanie
mogło być zastąpione przez
va_list aq;
va_copy(aq, ap);
...
va_end(aq);
Każdemu wywołaniu va_copy() musi odpowiadać wywołanie va_end() w obrębie tej samej funkcji. Niektóre
systemy nieudostępniające va_copy() mają zamiast niej __va_copy, gdyż ta nazwa była używana w szkicu
standardu.
ATRYBUTY
Wielowątkowość (patrz pthreads(7)) Makra va_start(), va_arg(), va_end() i va_copy() są bezpieczne dla wątków.
ZGODNE Z
Makra va_start(), va_arg() oraz va_end() są zgodne z C89. C99 opisuje makro va_copy().
UWAGI
Makra te nie są zgodne z historycznymi makrami, które zastąpiły. Zgodna wstecznie wersja znajduje się w
pliku nagłówkowym <varargs.h>.
Historyczna konfiguracja to:
#include <varargs.h>
void
foo(va_alist)
va_dcl
{
va_list ap;
va_start(ap);
while (...) {
...
x = va_arg(ap, type);
...
}
va_end(ap);
}
W niektórych systemach, va_end zawiera zamykający "}" odpowiadający "{" w va_start, tak żeby obydwa makra
musiały wystąpić w tej samej funkcji w dozwolony sposób.
USTERKI
W przeciwieństwie do makr varargs, makra stdarg nie zezwalają programistom na tworzenie funkcji bez
ustalonych argumentów. Problem ten powoduje utrudnienia podczas konwersji kodu varargs na kod stdarg, a
także utrudnia tworzenie funkcji, które mają za zadanie jedynie przekazać wszystkie swoje argumenty do
funkcji pobierającej argument va_list, takiej jak vfprintf(3).
PRZYKŁAD
Funkcja foo pobiera łańcuch znaków formatujących i wypisuje argumenty z nimi związane w oparciu o typ
argumentu.
#include <stdio.h>
#include <stdarg.h>
void
foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
switch (*fmt++) {
case 's': /* string */
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd': /* int */
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c': /* char */
/* występuje tu potrzeba rzutowania, gdyż va_arg
pobiera w pełni awansowane typy */
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break;
}
va_end(ap);
}
O STRONIE
Angielska wersja tej strony pochodzi z wydania 3.71 projektu Linux man-pages. Opis projektu, informacje
dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem
http://www.kernel.org/doc/man-pages/.
TŁUMACZENIE
Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Przemek Borys (PTM)
<pborys@dione.ids.pl>, Andrzej Krzysztofowicz (PTM) <ankry@mif.pg.gda.pl>, Robert Luberda
<robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>.
Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie
http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 3.71 oryginału.
2013-12-10 STDARG(3)