stdarg

Autres langues

Langue: pl

Autres versions - même langue

Version: 2001-10-14 (openSuse - 09/10/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).