Funcții Indicatori în programarea C cu exemple
⚡ Rezumat inteligent
Pointerii de funcție în C stochează adresa codului executabil, permițând programelor să apeleze funcții indirect, să le transmită ca argumente, să construiască tabele de dispecerizare din tablouri și să implementeze apeluri inverse, cum ar fi rutina de comparație qsort, pentru design-uri flexibile și reutilizabile.
Pointerii oferă foarte multe posibilități funcțiilor „C” pentru care suntem limitați să returnăm o valoare. Cu parametrii pointer, funcțiile noastre pot procesa acum date reale, mai degrabă decât o copie a datelor.
Pentru a modifica valorile reale ale variabilelor, instrucțiunea de apelare transmite adrese parametrilor pointer într-o funcție.
Funcții Indicatori Exemplu
De exemplu, următorul program schimbă două valori din două:
void swap (int *a, int *b); int main() { int m = 25; int n = 100; printf("m is %d, n is %d\n", m, n); swap(&m, &n); printf("m is %d, n is %d\n", m, n); return 0;} void swap (int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp;} }
ieșire:
m is 25, n is 100 m is 100, n is 25
Programul schimbă valorile reale ale variabilelor, deoarece funcția le accesează folosind adresa indicatorul. Aici vom discuta despre procesul programului:
- Declarăm funcția responsabilă pentru swapping cele două valori variabile, care primește doi pointeri întregi ca parametri și returnează orice valoare atunci când este apelată.
- În funcția principală, declarăm și inițializam două variabile întregi ('m' și 'n'), apoi imprimăm valorile acestora.
- Apelăm funcția swap() prin trecerea adresei celor două variabile ca argumente folosind simbolul ampersand. După aceea, imprimăm noile valori schimbate ale variabilelor.
- Aici definim conținutul funcției swap() care ia ca parametri două adrese de variabile întregi și declarăm o variabilă întreagă temporară folosită ca a treia casetă de stocare pentru a salva una dintre variabilele de valoare care va fi pusă la a doua variabilă.
- Salvați conținutul primei variabile indicată de „a” în variabila temporară.
- Stocați a doua variabilă indicată de b în prima variabilă indicată de a.
- Actualizați a doua variabilă (indicată cu b) cu valoarea primei variabile salvate în variabila temporară.
Funcții cu parametrii de matrice
În C, nu putem transmite o matrice după valoare unei funcții. Întrucât, un nume de matrice este un pointer (adresă), deci trecem doar un nume de matrice unei funcții, ceea ce înseamnă să transmitem un pointer matricei.
De exemplu, luăm în considerare următorul program:
int add_array (int *a, int num_elements); int main() { int Tab[5] = {100, 220, 37, 16, 98}; printf("Total summation is %d\n", add_array(Tab, 5)); return 0;} int add_array (int *p, int size) { int total = 0; int k; for (k = 0; k < size; k++) { total += p[k]; /* it is equivalent to total +=*p ;p++; */} return (total);}
ieșire:
Total summation is 471
Aici, vom explica codul programului cu detaliile acestuia
- Declarăm și definim funcția add_array() care ia o adresă de matrice (pointer) cu numărul de elemente ca parametri și returnează suma totală acumulată a acestor elemente. Pointerul este folosit pentru a itera elementele matricei (folosind notația p[k]) și acumulăm suma într-o variabilă locală care va fi returnată după iterarea întregului tablou de elemente.
- Declaram si initializam un tablou intreg cu cinci elemente intregi. Tipărim suma totală trecând numele matricei (care acționează ca adresă) și dimensiunea matricei către add_array()numită funcție ca argumente.
Funcții care returnează o matrice
În C, putem returna un pointer către o matrice, ca în următorul program:
#include <stdio.h> int * build_array(); int main() { int *a; a = build_array(); /* get first 5 even numbers */ for (k = 0; k < 5; k++) printf("%d\n", a[k]); return 0;} int * build_array() { static int Tab[5]={1,2,3,4,5}; return (Tab);}
ieșire:
1 2 3 4 5
Și aici, vom discuta detaliile programului
- Definim și declarăm o funcție care returnează o adresă matrice care conține o valoare întreagă și nu a luat niciun argument.
- Declaram un pointer intreg care primeste matricea completa construita dupa apelarea functiei si printam continutul acestuia prin iterarea intregii matrice de cinci elemente.
Observați că un pointer, nu o matrice, este definit pentru a stoca adresa matricei returnată de funcție. De asemenea, observați că atunci când o variabilă locală este returnată de la o funcție, trebuie să o declarăm ca statică în funcție.
Indicatori de funcție
După cum știm prin definiție că pointerii indică o adresă în orice locație de memorie, ei pot indica, de asemenea, la începutul codului executabil ca funcții din memorie.
Un pointer către funcție este declarat cu * , declarația generală a declarației sale este:
return_type (*function_name)(arguments)
Trebuie să vă amintiți că parantezele din jurul (*function_name) sunt importante deoarece fără ele, compilatorul va crede că function_name returnează un pointer de return_type.
După definirea indicatorului de funcție, trebuie să-l atribuim unei funcții. De exemplu, următorul program declară o funcție obișnuită, definește un pointer de funcție, atribuie pointerul funcției funcției obișnuite și apoi apelează funcția prin indicator:
#include <stdio.h> void Hi_function (int times); /* function */ int main() { void (*function_ptr)(int); /* function pointer Declaration */ function_ptr = Hi_function; /* pointer assignment */ function_ptr (3); /* function call */ return 0;} void Hi_function (int times) { int k; for (k = 0; k < times; k++) printf("Hi\n");}
ieșire:
Hi Hi Hi
- Definim și declarăm o funcție standard care afișează un text Hi k ori indicat de parametrul ori când funcția este apelată
- Definim o functie pointer (cu declaratia sa speciala) care preia un parametru intreg si nu returneaza nimic.
- Inițializam funcția de indicator cu Hi_function, ceea ce înseamnă că pointerul indică Hi_function().
- În loc de apelarea standard a funcției de către taping numele funcției cu argumente, apelăm doar funcția pointer transmițând numărul 3 ca argumente și gata!
Rețineți că numele funcției indică adresa de început a codului executabil ca un nume de matrice care indică primul său element. Prin urmare, instrucțiuni precum function_ptr = &Hi_function și (*funptr)(3) sunt corecte.
NOTĂ: Nu este important să introduceți operatorul de adresă & și operatorul indirect * în timpul atribuirii funcției și apelului de funcție.
Matrice de indicatori de funcție
O serie de indicatori de funcție poate juca un rol de comutare sau un rol de declarație if pentru a lua o decizie, ca în programul următor:
#include <stdio.h> int sum(int num1, int num2); int sub(int num1, int num2); int mult(int num1, int num2); int div(int num1, int num2); int main() { int x, y, choice, result; int (*ope[4])(int, int); ope[0] = sum; ope[1] = sub; ope[2] = mult; ope[3] = div; printf("Enter two integer numbers: "); scanf("%d%d", &x, &y); printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: "); scanf("%d", &choice); result = ope[choice](x, y); printf("%d", result); return 0;} int sum(int x, int y) {return(x + y);} int sub(int x, int y) {return(x - y);} int mult(int x, int y) {return(x * y);} int div(int x, int y) {if (y != 0) return (x / y); else return 0;}
Enter two integer numbers: 13 48
Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2
624
Aici, discutăm detaliile programului:
- Declaram si definim patru funcții care primesc două argumente întregi și returnează o valoare întreagă. Aceste funcții adună, subtract, înmulțiți și împărțiți cele două argumente referitoare la funcția apelată de utilizator.
- Declarăm 4 numere întregi pentru a gestiona operanzi, tipul operației și, respectiv, rezultat. De asemenea, declarăm o matrice cu patru indicatori de funcție. Fiecare indicator de funcție al elementului de matrice ia doi parametri întregi și returnează o valoare întreagă.
- Atribuim și inițializam fiecare element de matrice cu funcția deja declarată. De exemplu, al treilea element care este al treilea indicator al funcției va indica funcția operației de multiplicare.
- Căutăm operanzi și tipul de operație de la utilizatorul tastat cu tastatura.
- Am apelat elementul de matrice adecvat (Function pointer) cu argumente și stocăm rezultatul generat de funcția corespunzătoare.
Instrucțiunea int (*ope[4])(int, int); definește matricea de pointeri de funcție. Fiecare element de matrice trebuie să aibă aceiași parametri și aceiași tip de returnare.
Rezultatul declarației = ope[choice](x, y); rulează funcția corespunzătoare în funcție de alegerea făcută de utilizator Cele două numere întregi introduse sunt argumentele transmise funcției.
Funcții Folosind pointeri void
Indicatorii de gol sunt utilizați în timpul declarațiilor de funcție. Folosim un tip de returnare void * permite returnarea oricărui tip. Dacă presupunem că parametrii noștri nu se modifică la trecerea la o funcție, o declarăm ca const.
De exemplu:
void * cube (const void *);
Luați în considerare următorul program:
#include <stdio.h> void* cube (const void* num); int main() { int x, cube_int; x = 4; cube_int = cube (&x); printf("%d cubed is %d\n", x, cube_int); return 0;} void* cube (const void *num) { int result; result = (*(int *)num) * (*(int *)num) * (*(int *)num); return result;}
Rezultat:
4 cubed is 64
Aici vom discuta detaliile programului:
- Definim și declarăm o funcție care returnează o valoare întreagă și ia o adresă de variabilă neschimbabilă fără un tip de date specific. Calculăm valoarea de cub a variabilei de conținut (x) indicată de indicatorul num și, deoarece este un pointer void, trebuie să scriem cast-o într-un tip de date întreg folosind o notație specifică (* tip de date) pointer și revenim valoarea cubului.
- Declaram operandul si variabila rezultat. De asemenea, ne inițializam operandul cu valoarea „4”.
- Apelăm funcția cub prin transmiterea adresei operandului și ne ocupăm de valoarea returnată în variabila rezultat
Punctorii de funcție ca argumente
O altă modalitate de a exploata un indicator de funcție prin trecerea acestuia ca argument unei alte funcție numită uneori „funcție de apel invers”, deoarece funcția de recepție „o apelează înapoi”.
În fișierul antet stdlib.h, funcția Quicksort „qsort()” folosește această tehnică, care este un algoritm dedicat sortării unui tablou.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
- void *base : void pointer către matrice.
- size_t num : Numărul elementului matricei.
- size_t width Dimensiunea elementului.
- int (*compare (const void *, const void *) : indicatorul funcției compus din două argumente și returnează 0 când argumentele au aceeași valoare, <0 când arg1 vine înaintea arg2 și >0 când arg1 vine după arg2.
Următorul program sortează o matrice de numere întregi de la un număr mic la un număr mare folosind funcția qsort():
#include <stdio.h> #include <stdlib.h> int compare (const void *, const void *); int main() { int arr[5] = {52, 14, 50, 48, 13}; int num, width, i; num = sizeof(arr)/sizeof(arr[0]); width = sizeof(arr[0]); qsort((void *)arr, num, width, compare); for (i = 0; i < 5; i++) printf("%d ", arr[ i ]); return 0;} int compare (const void *elem1, const void *elem2) { if ((*(int *)elem1) == (*(int *)elem2)) return 0; else if ((*(int *)elem1) < (*(int *)elem2)) return -1; else return 1;}
Rezultat:
13 14 48 50 52
Aici vom discuta detaliile programului:
- Definim funcția de comparare compusă din două argumente și returnează 0 când argumentele au aceeași valoare, <0 când arg1 vine înaintea arg2 și >0 când arg1 vine după arg2. Parametrii sunt un tip de pointeri void turnați la tipul de date matrice adecvat. (întreg)
- Definim și inițializam un tablou întreg. Dimensiunea matricei este stocată în o variabilă și dimensiunea fiecărui element de matrice este stocată în variabilă de lățime folosind sizeof() predefinit operator C.
- Apelăm funcția qsort și transmitem numele tabloului, dimensiunea, lățimea și funcția de comparație definite anterior de utilizator pentru a sorta tabloul nostru în ordine crescătoare. Comparația se va efectua prin luarea în fiecare iterație a două elemente ale tabloului până când întregul tablou va fi sortat.
- Tipărim elementele matricei pentru a ne asigura că matricea noastră este bine sortată prin iterarea întregii matrice folosind pentru bucla.








