Ce face Pointeri la funcții
Numele unei funcții, folosit fără paranteze, este adresa ei. Un pointer la funcție ține o astfel de adresă și poate apela funcția: op(2, 3) sau (*op)(2, 3), ambele forme sunt corecte.
Sintaxa declarației pune numele între paranteze cu steluță: int (*op)(int, int). Fără paranteze, int *op(int, int) ar fi o funcție care returnează int *. Cu typedef, tipul primește un nume scurt și codul devine mai ușor de citit.
Pointerii la funcții permit codul generic: qsort primește funcția de comparare, un meniu poate ține acțiunile într-un tablou, o bibliotecă poate apela funcția ta când se întâmplă ceva (callback).
Exemple
Exemplul 1: Un calculator cu tablou de funcții
#include <stdio.h>
int aduna(int a, int b) { return a + b; }
int scade(int a, int b) { return a - b; }
int inmulteste(int a, int b) { return a * b; }
int main(void) {
int (*operatii[])(int, int) = {aduna, scade, inmulteste};
const char *simboluri = "+-*";
for (int i = 0; i < 3; i++) {
printf("12 %c 4 = %d\n", simboluri[i], operatii[i](12, 4));
}
return 0;
}
Rezultat
12 + 4 = 16
12 - 4 = 8
12 * 4 = 48
Exemplul 2: Callback cu typedef
aplica nu știe ce transformare face; primește funcția ca parametru și o aplică fiecărui preț.
#include <stdio.h>
typedef double (*Transformare)(double);
double cu_tva(double p) { return p * 1.21; }
double reducere_10(double p) { return p * 0.9; }
void aplica(double *preturi, int n, Transformare f) {
for (int i = 0; i < n; i++) {
preturi[i] = f(preturi[i]);
}
}
int main(void) {
double preturi[] = {100, 250, 40};
aplica(preturi, 3, cu_tva);
aplica(preturi, 3, reducere_10);
for (int i = 0; i < 3; i++) {
printf("%.2f lei\n", preturi[i]);
}
return 0;
}
Rezultat
108.90 lei
272.25 lei
43.56 lei
Exemplul 3: Alegerea funcției la rulare
Pointerul primește o funcție sau alta după o condiție; apelul rămâne același.
#include <stdio.h>
void salut_ro(const char *nume) { printf("Bună, %s!\n", nume); }
void salut_en(const char *nume) { printf("Hello, %s!\n", nume); }
int main(void) {
const char *limba = "ro";
void (*salut)(const char *) = (limba[0] == 'r') ? salut_ro : salut_en;
salut("Ana");
salut = salut_en;
salut("Ana");
return 0;
}
Rezultat
Bună, Ana!
Hello, Ana!
Greșeli frecvente
- Scrii
int *op(int, int);când voiai un pointer la funcție. Asta declară o funcție care returneazăint *; corect:int (*op)(int, int);. - Apelezi un pointer la funcție neinițializat sau nul. Programul se oprește; verifică
if (op)înainte, dacă pointerul poate lipsi. - Faci cast între pointeri la funcții cu semnături diferite și apelezi prin ei. Apelul printr-un tip nepotrivit este comportament nedefinit.
Comenzi înrudite
qsort: Sortează un tablou de orice tip, folosind o funcție de comparare scrisă de tine.bsearch: Caută rapid un element într-un tablou sortat (căutare binară) și întoarce un pointer la el sau NULL.typedef: Dă un nume nou, mai scurt sau mai clar, unui tip existent: o structură, un pointer sau un tip de funcție.Funcții și prototipuri: Cum definești și declari funcții în C: tipul rezultatului, parametrii, prototipul și transmiterea argumentelor prin valoare.exit, atexit și EXIT_SUCCESS: Oprește programul din orice funcție, cu un cod de ieșire; atexit înregistrează funcții de rulat la final.