NAZWA¶
stdarg - 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¶
Uwaga! To tłumaczenie może być nieaktualne!
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 poprzez 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 jako pierwsze.
Parametr
last jest nazwą ostatniego parametru przed zmienną
listą argumentów, czyli ostatnim parametrem, którego typ
był funkcji znany.
Ponieważ adres tego parametru jest używany w makrze
va_start,
nie powinien on 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. Parametr
ap to
va_list ap zainicjowany przez
va_start.
Każde wywołanie
va_arg zmienia
ap tak, że
następne wywołanie zwraca następny argument. Parametr
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(ap) 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¶
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 przeciwskazań
wobec podstawienia
Niestety, są również systemy, które robią to poprzez
tablicę wskaźników (o długości 1) i wtedy
niezbędne jest
Wreszcie, w systemach, które przekazują parametry w rejestrach,
może okazać się koniecznym przydzielenie pamięci przez
va_start, przechowanie tam parametrów, jak też wskazań,
który parametr 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 byc 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 nie
udostępniające
va_copy posiadają zamiast tego
__va_copy, gdyż ta nazwa była używana w szkicowej
propozycji standardu.
PRZYKŁADY¶
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, *p, *s;
va_start(ap, fmt);
while (*fmt)
switch(*fmt++) {
case 's': /* napis */
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);
}
ZGODNE Z¶
Makra
va_start,
va_arg, i
va_end są zgodne z ANSI
X3.159-1989 (``C89''). C99 definiuje makro
va_copy.
KOMPATYBILNOŚĆ¶
Makra te
nie są zgodne z historycznymi makrami, które
zastąpiły. Zgodna wstecznie wersja znajduje się w pliku
nagłówkowym
varargs.h.
PORÓWNANIE¶
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).
Powyższe tłumaczenie pochodzi z nieistniejącego już Projektu
Tłumaczenia Manuali i
może nie być aktualne. W razie
zauważenia różnic między powyższym opisem a
rzeczywistym zachowaniem opisywanego programu lub funkcji, prosimy o
zapoznanie się z oryginalną (angielską) wersją strony
podręcznika za pomocą polecenia:
- man --locale=C 3 stdarg
Prosimy o pomoc w aktualizacji stron man - więcej informacji można
znaleźć pod adresem
http://sourceforge.net/projects/manpages-pl/.