Pointeri la functii
In limbajul C o functie nu este o variabila, dar putem defini un pointer la o functie, care apoi poate fi prelucrat, transmis unor alte functii, introdus intr-un masiv si asa mai departe. Relativ la o functie se pot face doar doua operatii: apelul ei si considerarea adresei ei. Daca numele unei functii apare intr-o expresie, fara a fi urmat imediat de o paranteza stinga, deci nu pe pozitia unui ape 353c24d l la ea, atunci se genereaza un pointer la aceasta functie. Pentru a transmite o functie unei alte functii, ca argument, se poate proceda in felul urmator:
int f();
g(f);
unde functia f este un argument pentru functia g. Definitia functiei g va fi:
g(int(*funcpt) ())
Functia f trebuie declarata explicit in rutina apelanta (int f();), deoarece aparitia ei in g(f) nu a fost urmata de paranteza stinga ’ ’. In expresia g(f) f nu apare pe pozitia de apel de functie. In acest caz, pentru argumentul functiei g se genereaza un pointer la functia f. Deci g apeleaza functia f printr-un pointer la ea.
Declaratiile din functia g trebuie studiate cu grija.
int (*funcpt)();
spune ca funcpt este un pointer la o functie care returneaza un intreg. Primul set de paranteze este necesar, deoarece fara el
int *funcpt();
inseamna ca funcpt este o functie care returneaza un pointer la un intreg, ceea ce este cu totul diferit fata de sensul primei expresii. Folosirea lui funcpt in expresia:
(*funcpt)();
indica faptul ca funcpt este un pointer la o functie, *funcpt este functia, iar (*funcpt)() este apelul functiei.
O forma echivalenta simplificata de apel este urmatoarea:
funcpt();
Ca un exemplu, sa consideram procedura de sortare a liniilor de la intrare, descrisa in sectiunea 9.7, dar modificata in sensul ca daca argumentul optional -n apare in linia de comanda, atunci liniile se vor sorta nu lexicografic ci numeric, liniile continind grupe de numere.
O sortare consta adesea din trei parti: o comparare care determina ordinea oricarei perechi de elemente, un schimb care inverseaza ordinea elementelor implicate si un algoritm de sortare care face compararile si inversarile pina cind elementele sint aduse in ordinea ceruta. Algoritmul de sortare este independent de operatiile de comparare si inversare, astfel incit transmitind diferite functii de comparare si inversare functiei de sortare, elementele de intrare se pot aranja dupa diferite criterii.
Compararea lexicografica a doua linii se realizeaza prin functiile strcmp si swap. Mai avem nevoie de o rutina numcmp care sa compare doua linii pe baza valorilor numerice si care sa returneze aceiasi indicatori ca si rutina strcmp
Declaram aceste trei functii in functia principala main, iar pointerii la aceste functii ii transmitem ca argumente functiei sort, care la rindul ei va apela aceste functii prin intermediul pointerilor respectivi.
#define LINES 100 /* nr maxim de linii de sortat */
main (int argc, char *argv[])
else
printf
('Nr de linii de intrare prea maren');
}
In apelul functiei sort, argumentele strcmp numcmp si swap sint adresele functiilor respective. Deoarece ele au fost declarate functii care returneaza un intreg, operatorul ’&’ nu este necesar sa preceada numele functiilor, compilatorul fiind cel care gestioneaza transmiterea adreselor functiilor.
sort(char *v[], int n, int (*comp)(),
int (*exch)())
}
Sa studiem declaratiile din aceasta functie.
int(*comp)(), (*exch)();
indica faptul ca comp si exch sint pointeri la functii care returneaza un intreg (primul set de paranteze este necesar).
if (comp(v[j],v[j+gap])<=0)
inseamna apelul functiei comp (adica strcmp sau numcmp), deoarece comp este un pointer la functie, *comp este functia, iar
comp(v[j],v[j+gap])
este apelul functiei.
exch(v+j,v+j+gap)
este apelul functiei swap, de inversare a doua linii, inversare care realizeaza interschimbarea adreselor liniilor implicate (vezi sectiunea 9.2). Functia numcmp este urmatoarea:
numcmp(char *s1, char *s2)
Pentru ca programul nostru sa fie complet sa mai prezentam si codul functiei swap, care schimba intre ei pointerii a doua linii.
swap(char *px[], char *py[]) {
char *temp;
temp = *px;
*px = *py;
*py = temp;
|