stdarg

Autres langues

Langue: pl

Autres versions - même langue

Version: 2001-10-14 (fedora - 25/11/07)

Section: 3 (Bibliothèques de fonctions)

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

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
         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ę 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).