Provided by: manpages-pl-dev_0.7-1_all bug

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

       Informacje   o   pojęciach   używanych   w  tym  rozdziale  można  znaleźć  w  podręczniku
       attributes(7).

       ┌──────────────────────┬────────────────────────┬─────────────────┐
       │InterfejsAtrybutWartość         │
       ├──────────────────────┼────────────────────────┼─────────────────┤
       │va_start(), va_end(), │ Bezpieczeństwo wątkowe │ MT-Safe         │
       │va_copy()             │                        │                 │
       ├──────────────────────┼────────────────────────┼─────────────────┤
       │va_arg()              │ Bezpieczeństwo wątkowe │ MT-Safe race:ap │
       └──────────────────────┴────────────────────────┴─────────────────┘

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  4.07  projektu  Linux  man-pages.  Opis
       projektu,  informacje  dotyczące  zgłaszania  błędów oraz najnowszą wersję oryginału można
       znaleźć pod adresem https://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ą   4.07
       oryginału.

                                            2015-03-02                                  STDARG(3)