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
floatcuva_arg(ap, float). Argumentul a fost promovat ladouble; citeștedouble. - Citești mai multe argumente decât au fost trimise.
va_argnu are cum să știe; rezultatul este comportament nedefinit. - Folosești
va_listde două ori fărăva_copysau un nouva_start. După ce l-ai parcurs (inclusiv cuvprintf), 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ă.
Î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.