stdarg(3) Library Functions Manual stdarg(3) NAZWA stdarg, va_start, va_arg, va_end, va_copy - listy zmiennych argumentow BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include 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 Funkcje mozna wolac z rozna liczba argumentow roznych typow. Plik naglowkowy deklaruje typ va_list i definiuje trzy makra, iterujace przez liste argumentow, ktorych liczba i typy nie sa znane wywolanej funkcji. Wywolana funkcja musi zadeklarowac obiekt typu va_list, ktory jest uzywany przez makra va_start(), va_arg() i va_end(). va_start() Makro va_start() inicjuje ap do dalszego uzytku przez va_arg() i va_end() i musi byc wywolane pierwsze. Parametr last jest nazwa ostatniego argumentu przed zmienna lista argumentow, czyli ostatnim argumentem, ktorego typ jest funkcji znany. Poniewaz adres tego parametru jest uzywany w makrze va_start(), nie powinien byc deklarowany jako zmienna rejestrowa, funkcja czy typ tablicowy. va_arg() Makro va_arg() rozwija sie do wyrazenia, ktore ma typ i wartosc nastepnego argumentu w wywolaniu. Argument ap to ap z va_list() zainicjowany przez va_start(). Kazde wywolanie va_arg() zmienia ap tak, ze nastepne wywolanie zwraca nastepny argument. Argument type jest nazwa typu, podana tak ze typ wskaznika do obiektu, ktory ma podany typ, mozna uzyskac przez dodanie * do type. Pierwsze uzycie makra va_arg() po va_start() zwraca argument za last (ostatnim). Kolejne wywolania zwracaja wartosci pozostalych argumentow. Jesli nie ma nastepnego argumentu lub jesli type nie jest zgodny z rzeczywistym typem nastepnego argumentu, pojawia sie losowe bledy. Jesli ap zostanie przekazane do funkcji uzywajacej va_arg(ap,type), to wartosc ap po zakonczeniu tej funkcji bedzie nieokreslona. va_end() Kazdemu wywolaniu va_start() musi odpowiadac wywolanie va_end() w obrebie tej samej funkcji. Po wywolaniu va_end() wartosc ap bedzie nieokreslona. Lista moze byc przetwarzana wielokrotnie, przy czym kazde przetworzenie musi byc zawarte pomiedzy va_start() a va_end(). va_end() moze byc zarowno makrem, jak i funkcja. va_copy() Makro va_copy() kopiuje (poprzednio zainicjowana) liste src argumentow o zmiennej dlugosci do dest. Zachowanie to jest takie samo, jakby va_start() zostalo zaaplikowane do dest z tym samym argumentem last, po ktorym nastepowalaby ta sama liczba wywolan va_arg(), ktora byla uzyta do tej pory, aby osiagnac biezacy stan zmiennej src. Oczywista implementacja zawieralaby wskaznik va_list do ramki stosu funkcji o zmiennej liczbie argumentow. Przy takiej konfiguracji (jak dotad, najpowszechniejszej) nie ma zadnych przeciwwskazan do podstawienia va_list aq = ap; Niestety, sa rowniez systemy, ktore robia to poprzez tablice wskaznikow (o dlugosci 1) i wtedy niezbedne jest va_list aq; *aq = *ap; Wreszcie, w systemach, ktore przekazuja parametry w rejestrach, moze okazac sie konieczne przydzielenie pamieci przez va_start(), przechowanie tam argumentow, jak tez wskazan, ktory argument jest nastepny, tak aby va_arg() moglo przejsc cala liste. Wowczas va_end() moze wreszcie zwolnic przydzielona w tym celu pamiec. Aby dostosowac sie do tej sytuacji, C99 dodaje makro va_copy(), tak aby powyzsze przypisanie moglo byc zastapione przez va_list aq; va_copy(aq, ap); ... va_end(aq); Kazdemu wywolaniu va_copy() musi odpowiadac wywolanie va_end() w obrebie tej samej funkcji. Niektore systemy nieudostepniajace va_copy() maja zamiast niej __va_copy, gdyz ta nazwa byla uzywana w szkicu standardu. ATRYBUTY Informacje o pojeciach uzywanych w tym rozdziale mozna znalezc w podreczniku attributes(7). +-------------------+--------------------------+-----------------------+ |Interfejs | Atrybut | Wartosc | +-------------------+--------------------------+-----------------------+ |va_start(), | Bezpieczenstwo watkowe | MT-bezpieczne | |va_end(), | | | |va_copy() | | | +-------------------+--------------------------+-----------------------+ |va_arg() | Bezpieczenstwo watkowe | MT-bezpieczne race:ap | +-------------------+--------------------------+-----------------------+ STANDARDY C11, POSIX.1-2008. HISTORIA va_start() va_arg() va_end() C89, POSIX.1-2001. va_copy() C99, POSIX.1-2001. ZASTRZEZENIA W przeciwienstwie do makr varargs, makra stdarg nie zezwalaja programistom na tworzenie funkcji bez ustalonych argumentow. Problem ten powoduje utrudnienia podczas konwersji kodu varargs na kod stdarg, a takze utrudnia tworzenie funkcji, ktore maja za zadanie jedynie przekazac wszystkie swoje argumenty do funkcji pobierajacej argument va_list, takiej jak vfprintf(3). PRZYKLADY Funkcja foo pobiera lancuch znakow formatujacych i wypisuje argumenty z nimi zwiazane w oparciu o typ argumentu. #include #include void foo(char *fmt, ...) /* '...' is C syntax for a variadic function */ { va_list ap; int d; char c; char *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 */ /* need a cast here since va_arg only takes fully promoted types */ c = (char) va_arg(ap, int); printf("char %c\n", c); break; } va_end(ap); } ZOBACZ TAKZE vprintf(3), vscanf(3), vsyslog(3) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Przemek Borys , Andrzej Krzysztofowicz , Robert Luberda i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.9.1 15 czerwca 2024 r. stdarg(3)