Funcții variadice (stdarg.h) în C

Funcții cu număr variabil de argumente, ca printf: le citești pe rând cu va_start, va_arg și va_end din stdarg.h.

Sintaxă
#include <stdarg.h>
tip f(tip ultimul_fix, ...);
va_list ap;
va_start(ap, ultimul_fix);   // C23: va_start(ap) este suficient
tip x = va_arg(ap, tip);
va_end(ap);

Ce face Funcții variadice (stdarg.h)

Trei puncte (...) la finalul listei de parametri înseamnă „oricâte argumente în plus”. Le citești cu macro-urile din stdarg.h: va_start pregătește citirea, va_arg(ap, tip) dă următorul argument, iar va_end încheie. Din C23, va_start(ap) merge și fără numele ultimului parametru fix, iar o funcție poate avea doar ....

Funcția nu află singură câte argumente a primit și de ce tip sunt. Trebuie să îi spui: printr-un număr trimis primul, printr-o valoare de oprire (de exemplu 0 sau nullptr) sau printr-un format, ca la printf.

Argumentele variadice trec prin promovările implicite: char și short devin int, float devine double. De aceea citești cu va_arg(ap, int) sau va_arg(ap, double). Pentru a trimite argumentele mai departe la printf, există vprintf, vfprintf, vsnprintf.

Exemple

Exemplul 1: Suma a n numere

Primul argument spune câte numere urmează.

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

int suma(int n, ...) {
    va_list ap;
    va_start(ap, n);
    int total = 0;
    for (int i = 0; i < n; i++) {
        total += va_arg(ap, int);
    }
    va_end(ap);
    return total;
}

int main(void) {
    printf("%d\n", suma(3, 10, 20, 30));
    printf("%d\n", suma(5, 1, 2, 3, 4, 5));
    return 0;
}

Rezultat

60
15

Exemplul 2: Listă oprită de nullptr

Funcția afișează șiruri până întâlnește nullptr. Valoarea de oprire trebuie pusă de cel care apelează.

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

void lista_orase(const char *primul, ...) {
    va_list ap;
    va_start(ap, primul);
    for (const char *oras = primul; oras != nullptr; oras = va_arg(ap, const char *)) {
        printf("- %s\n", oras);
    }
    va_end(ap);
}

int main(void) {
    lista_orase("Iași", "Cluj-Napoca", "Timișoara", nullptr);
    return 0;
}

Rezultat

- Iași
- Cluj-Napoca
- Timișoara

Exemplul 3: Funcție de jurnal care trimite mai departe la vprintf

jurnal adaugă un prefix și dă formatul cu argumentele lui vprintf. Atributul format (extensie GCC/Clang) îi permite compilatorului să verifice argumentele ca la printf.

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

__attribute__((format(printf, 2, 3)))
void jurnal(const char *nivel, const char *format, ...) {
    va_list ap;
    va_start(ap, format);
    printf("[%s] ", nivel);
    vprintf(format, ap);
    printf("\n");
    va_end(ap);
}

int main(void) {
    jurnal("INFO", "Utilizatorul %s s-a conectat din %s", "ana", "Iași");
    jurnal("EROARE", "Stoc insuficient: %d bucăți, cerute %d", 2, 5);
    return 0;
}

Rezultat

[INFO] Utilizatorul ana s-a conectat din Iași
[EROARE] Stoc insuficient: 2 bucăți, cerute 5

Greșeli frecvente

  • Citești un float cu va_arg(ap, float). Argumentul a fost promovat la double; citește double.
  • Citești mai multe argumente decât au fost trimise. va_arg nu are cum să știe; rezultatul este comportament nedefinit.
  • Folosești va_list de două ori fără va_copy sau un nou va_start. După ce l-ai parcurs (inclusiv cu vprintf), conținutul nu mai este valabil.

Comenzi înrudite

  • printf: Afișează text formatat pe ecran: un șablon cu specificatori (%d, %s, %.2f) completați cu valorile primite după el.
  • snprintf și sprintf: Formatează text ca printf, dar îl scrie într-un tablou de caractere; snprintf nu depășește niciodată dimensiunea dată.
  • Funcții și prototipuri: Cum definești și declari funcții în C: tipul rezultatului, parametrii, prototipul și transmiterea argumentelor prin valoare.
  • Macro cu parametri: Macro care primesc argumente, ca o funcție: textul lor este copiat în locul apelului, cu operatorii # și ## și argumente variabile.
  • Atribute [[...]]: Atributele C23 dau compilatorului informații în plus: rezultat care nu trebuie ignorat, funcție învechită, variabilă poate nefolosită.
Comunitate & Schimb de cunoștințe

Întrebări & Exemple de Cod: Funcții variadice (stdarg.h)

Ai o nelămurire despre utilizarea comenzii Funcții variadice (stdarg.h) sau ai descoperit un truc / fragment de cod util? Distribuie-l cu ceilalți programatori!

💬

Fii primul care pune o întrebare sau distribuie un fragment de cod / prompt!

Nu au fost adăugate încă întrebări sau exemple de cod pentru această pagină. Dacă ai întâlnit o problemă sau ai un snippet util, adaugă-l mai jos pentru a-i ajuta pe ceilalți.

Comunitate Adaugă o întrebare sau distribuie un cod

Moderare & Siguranță:

Pentru a menține calitatea și securitatea informațiilor, fiecare întrebare sau fragment de cod/prompt este analizat (manual sau prin moderare asistată de AI) înainte de publicare.