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)