stdarg(3)

NUME
stdarg, va_start, va_arg, va_end, va_copy - liste de argumente variabile

BIBLIOTECA
Biblioteca C standard (libc, -lc)

SINOPSIS
#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);

DESCRIERE
O funcție poate fi apelată cu un număr variabil de argumente de diferite tipuri. Fișierul de includere <stdarg.h> declară un tip va_list și definește trei macro pentru parcurgerea unei liste de argumente al căror număr și tipuri nu sunt cunoscute de funcția apelată.

Funcția apelată trebuie să declare un obiect de tip va_list care este utilizat de macrocomenzile va_start(), va_arg() și va_end().

  va_start()
Macrocomanda va_start() inițializează ap pentru utilizarea ulterioară de către va_arg() și va_end() și trebuie să fie apelată prima.

Argumentul last este numele ultimului argument înainte de lista de argumente a variabilei, adică ultimul argument al cărui tip este cunoscut de către funcția apelantă.

Deoarece adresa acestui argument poate fi utilizată în macrocomanda va_start(), acesta nu trebuie să fie declarat ca o variabilă de registru sau ca o funcție sau un tip de matrice.

  va_arg()
Macrocomanda va_arg() se extinde la o expresie care are tipul și valoarea următorului argument din apel. Argumentul ap este va_list ap inițializat de va_start(). Fiecare apel la va_arg() modifică ap astfel încât următorul apel returnează următorul argument. Argumentul type este un nume de tip specificat astfel încât tipul unui indicator la un obiect care are tipul specificat să poată fi obținut prin simpla adăugare a unui * la type.

Prima utilizare a macrocomenzii va_arg() după cea a macrocomenzii va_start() returnează argumentul după last. Invocările succesive returnează valorile celorlalte argumente.

În cazul în care nu există un argument următor sau dacă tip nu este compatibil cu tipul argumentului următor real (promovat în conformitate cu promoțiile de argumente implicite), vor apărea erori aleatorii.

Dacă ap este pasat unei funcții care utilizează va_arg(ap,tip), atunci valoarea lui ap este nedefinită după returnarea acelei funcții.

  va_end()
Fiecare invocare a va_start() trebuie să fie însoțită de o invocare corespunzătoare a va_end() în cadrul aceleiași funcții. După apelul va_end(ap), variabila ap este nedefinită. Sunt posibile mai multe parcurgeri ale listei, fiecare dintre ele între paranteze de va_start() și va_end(). va_end() poate fi o macrocomandă sau o funcție.

  va_copy()
Macrocomanda va_copy() copiază lista de argumente variabile (inițializată anterior) src în dest. Comportamentul este ca și cum va_start() ar fi aplicat la dest cu același argument last, urmat de același număr de invocări va_arg() care a fost utilizat pentru a ajunge la starea actuală a src.

O implementare evidentă ar fi ca va_list să fie un indicator la cadrul de stivă al funcției cu număr de argumente variabile. Într-o astfel de configurație (de departe cea mai comună) nu pare să existe nimic împotriva unei atribuiri

    va_list aq = ap;

Din nefericire, există și sisteme care o transformă într-o matrice de indicatori (de lungime 1), iar acolo este nevoie de

    va_list aq;
    *aq = *ap;

În cele din urmă, pe sistemele în care argumentele sunt transmise în registre, poate fi necesar ca va_start() să aloce memorie, să stocheze acolo argumentele, precum și o indicație a argumentului care urmează, astfel încât va_arg() să poată parcurge lista. Acum, va_end() poate elibera din nou memoria alocată. Pentru a se adapta la această situație, C99 adaugă o macrocomandă va_copy(), astfel încât atribuirea de mai sus poate fi înlocuită cu

    va_list aq;
    va_copy(aq, ap);
    ...
    va_end(aq);

Fiecare invocare a va_copy() trebuie să fie însoțită de o invocare corespunzătoare a va_end() în cadrul aceleiași funcții. Unele sisteme care nu furnizează va_copy() au în schimb __va_copy, deoarece acesta a fost numele utilizat în proiectul de propunere.

ATRIBUTE
Pentru o explicație a termenilor folosiți în această secțiune, a se vedea attributes(7).
Interfață | Atribut | Valoare
va_start(), va_end(), va_copy() | Siguranța firelor | MT-Safe
va_arg() | Siguranța firelor | MT-Safe race:ap

STANDARDE
C11, POSIX.1-2008.

ISTORIC

va_start()
va_arg()
va_end()
    C89, POSIX.1-2001.

va_copy()
    C99, POSIX.1-2001.

AVERTISMENTE
Spre deosebire de macrocomenzile istorice varargs, macrocomenzile stdarg nu permit programatorilor să codifice o funcție fără argumente fixe. Această problemă generează muncă mai ales la convertirea codului varargs în cod stdarg, dar creează dificultăți și pentru funcțiile cu număr de argumente variabile, „variadice”, care doresc să transmită toate argumentele lor unei funcții care ia un argument va_list, cum ar fi vfprintf(3).

EXEMPLE
Funcția foo preia un șir de caractere de format și afișează argumentul asociat fiecărui caracter de format în funcție de tip.

    #include <stdio.h>
    #include <stdarg.h>

    void
    foo(char *fmt, ...)   /* '...' este sintaxa C pentru o funcție variadică */

    {
        va_list ap;
        int d;
        char c;
        char *s;

        va_start(ap, fmt);
        while (*fmt)
            switch (*fmt++) {
            case 's':              /* șir */
                s = va_arg(ap, char *);
                printf("șir %s\n", s);
                break;
            case 'd':              /* număr întreg */
                d = va_arg(ap, int);
                printf("număr întreg %d\n", d);
                break;
            case 'c':              /* caracter */
                /* avem nevoie de o conversie de tip aici,
                   deoarece va_arg acceptă numai
                   tipuri complet promovate */
                c = (char) va_arg(ap, int);
                printf("caracter %c\n", c);
                break;
            }
        va_end(ap);
    }

CONSULTAȚI ȘI
vprintf(3), vscanf(3), vsyslog(3)

TRADUCERE
Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>

Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 (https://www.gnu.org/licenses/gpl-3.0.html) sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.

Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.