În C putem defini funcţii în care numărul de argumente (parametri) nu este fix. Putem apela o astfel de funcţie cu oricâţi parametri. Din această categorie fac parte funcţiile printf
şi scanf
.
Ne propunem să scriem o funcţie care să poată găsi maximul oricâtor valori transmise ca parametri, fără a folosi vectori. O funcţie cu listă variabilă de argumente se defineşte astfel:
tip_ret fctvarlist(tip prim, ...)
După numele funcţiei, între paranteze se dau tipul şi denumirea primului parametru de apel al funcţiei, urmate de virgulă şi de trei puncte. În consecinţă o funcţie cu listă variabilă de argumente trebuie să aibă cel puţin un parametru când este apelată. Primul parametru de apel dă de obicei informaţii cu privire numărul de parametri de apel şi eventual cu privire la tipul parametrilor, aşa cum se întâmplă şi în cazul funcţiilor printf
şi scanf
.
Implementarea unei funcţii cu listă variabilă de argumente se face cu ajutorul macrourilor va_start
, va_arg
şi va_end
. Aceste macro-uri sunt definite în fişierul antet stdarg.h
. Pentru a identifica parametrii de apel, în interiorul corpului unei funcţii având listă variabilă de argumente se defineşte o variabilă de tip va_list
, care este un vector definit în fişierul antet stdarg.h
. Acest vector reţine practic informaţiile cu privire la transmiterea parametrilor. Pe baza acestor informaţii şi cu ajutorul celor trei macro-uri (va_start
, va_arg
şi va_end
) se pot identifica valorile parametrilor de apel ai funcţiei.
Macro-ul va_start
setează vectorul va_list
aşa încât să indice primul parametru de apel al funcţiei. El are doi parametri. Primul este vectorul de tip va_list
, iar al doilea este variabila în care se depune valoarea primului parametru de apel al funcţiei. Această variabilă trebuie să fie dată explicit ca prim argument în definiţia funcţiei.
Apelând succesiv macro-ul va_arg
, se identifică restul parametrilor de apel ai funcţiei (de la al doilea până la ultimul). Macro-ul va_arg
se transformă într-o expresie care are acelaşi tip şi aceeaşi valoare cu următorul parametru de apel al funcţiei. Expresia se generează pe baza celor doi parametri ai macro-ului. Primul parametru
este vectorul de tip va_list
, iar al doilea este tipul la care se converteşte expresia. Acest tip de
dată trebuie evident să fie cel al parametrului de apel.
Trebuie reţinut faptul că datorită mecanismului promovării din C (convertirea automată a unui tip la unul superior din aceeaşi categorie) funcţiile cu listă variabilă de parametri nu funcţionează corect pentru tipurile de dată char
, unsigned char
şi float
.
Macro-ul va_end
se apelează după ce toţi parametrii de apel ai funcţiei cu listă variabilă de argumente au fost identificaţi. Acest macro ajută ca ieşirea din funcţie să se facă în condiţii bune.
#include <stdio.h>
#include <conio.h>
#include <stdarg.h>
double max(int n,...) //functie cu lista variabila de argumente
{
va_list lista_arg;
int i;
double max = -1E10, arg;
va_start (lista_arg,n);
for (i = 0; i < n; i++)
{
arg = va_arg (lista_arg, double);
if (arg > max)
max = arg;
}
va_end (lista_arg);
return max;
}
void main()
{
printf ("Maximul este: %lf\n",max (5, -1., 5., -3.7, 4.9, 0.));
getch();
}