Funktionspekare i C-programmering med exempel
Pekare ger stora möjligheter till "C"-funktioner som vi är begränsade till att returnera ett värde. Med pekparametrar kan våra funktioner nu behandla faktiska data snarare än en kopia av data.
För att modifiera de faktiska värdena för variabler skickar den anropande satsen adresser till pekparametrar i en funktion.
Funktioner Pekare Exempel
Till exempel byter nästa program två värden av två:
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;} }
Produktion:
m is 25, n is 100 m is 100, n is 25
Programmet byter ut de faktiska variablernas värden eftersom funktionen kommer åt dem genom att använda adress pekare. Här kommer vi att diskutera programprocessen:
- Vi förklarar funktionen som är ansvarig för att byta de två variabelvärdena, som tar två heltalspekare som parametrar och returnerar vilket värde som helst när det anropas.
- I huvudfunktionen deklarerar och initierar vi två heltalsvariabler ('m' och 'n') och sedan skriver vi ut deras respektive värden.
- Vi anropar swap()-funktionen genom att skicka adressen till de två variablerna som argument med et-tecken. Efter det skriver vi ut de nya utbytta värdena för variabler.
- Här definierar vi swap()-funktionens innehåll som tar två heltalsvariabeladresser som parametrar och deklarerar en temporär heltalsvariabel som används som en tredje lagringsbox för att spara en av värdevariablerna som kommer att läggas till den andra variabeln.
- Spara innehållet i den första variabeln som pekas med 'a' i den temporära variabeln.
- Lagra den andra variabeln som pekas av b i den första variabeln som pekas av a.
- Uppdatera den andra variabeln (pekad med b) med värdet på den första variabeln som sparats i den temporära variabeln.
Fungerar med Array-parametrar
I C kan vi inte skicka en matris efter värde till en funktion. Medan ett arraynamn är en pekare (adress), så vi skickar bara ett arraynamn till en funktion som betyder att skicka en pekare till arrayen.
Vi överväger till exempel följande 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);}
Produktion:
Total summation is 471
Här kommer vi att förklara programkoden med dess detaljer
- Vi deklarerar och definierar add_array()-funktionen som tar en arrayadress(pekare) med dess elementnummer som parametrar och returnerar den totala ackumulerade summan av dessa element. Pekaren används för att iterera arrayelementen (med p[k]-notationen), och vi ackumulerar summeringen i en lokal variabel som kommer att returneras efter att ha itererat hela elementarrayen.
- Vi deklarerar och initierar en heltalsarray med fem heltalselement. Vi skriver ut den totala summeringen genom att skicka arraynamnet (som fungerar som adress) och arraystorleken till add_array()kallas funktion som argument.
Funktioner som returnerar en array
I C kan vi returnera en pekare till en array, som i följande 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);}
Produktion:
1 2 3 4 5
Och här kommer vi att diskutera programdetaljerna
- Vi definierar och deklarerar en funktion som returnerar en matrisadress som innehåller ett heltalsvärde och som inte tog några argument.
- Vi deklarerar en heltalspekare som tar emot hela arrayen som byggts efter att funktionen anropats och vi skriver ut dess innehåll genom att iterera hela arrayen med fem element.
Observera att en pekare, inte en array, är definierad för att lagra arrayadressen som returneras av funktionen. Observera också att när en lokal variabel returneras från en funktion, måste vi deklarera den som statisk i funktionen.
Funktionspekare
Som vi per definition vet att pekare pekar på en adress på valfri minnesplats, kan de också peka på i början av körbar kod som funktioner i minnet.
En pekare till funktion deklareras med * , det allmänna uttalandet i dess deklaration är:
return_type (*function_name)(arguments)
Du måste komma ihåg att parenteserna runt (*funktionsnamn) är viktiga för utan dem kommer kompilatorn att tro att funktionsnamnet returnerar en pekare av returtyp.
Efter att ha definierat funktionspekaren måste vi tilldela den till en funktion. Till exempel deklarerar nästa program en vanlig funktion, definierar en funktionspekare, tilldelar funktionspekaren till den vanliga funktionen och efter det anropar funktionen genom pekaren:
#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");}
Produktion:
Hi Hi Hi
- Vi definierar och deklarerar en standardfunktion som skriver ut en Hi-text k gånger indikerade av parametern gånger när funktionen anropas
- Vi definierar en pekarfunktion (med dess speciella deklaration) som tar en heltalsparameter och inte returnerar något.
- Vi initierar vår pekarfunktion med Hi_function vilket innebär att pekaren pekar på Hi_function().
- I stället för att standardfunktionen anropar genom att tejpa funktionsnamnet med argument, anropar vi bara pekarfunktionen genom att skicka siffran 3 som argument, och det är allt!
Tänk på att funktionsnamnet pekar på startadressen för den körbara koden som ett arraynamn som pekar på dess första element. Därför är instruktioner som function_ptr = &Hi_function och (*funptr)(3) korrekta.
OBS: Det är inte viktigt att sätta in adressoperatören & och inriktningsoperatören * under funktionstilldelningen och funktionsanropet.
Array av funktionspekare
En rad funktionspekare kan spela en switch eller en if-uttalande roll för att fatta ett beslut, som i nästa program:
#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
Här diskuterar vi programdetaljerna:
- Vi deklarerar och definierar fyra funktioner som tar två heltalsargument och returnerar ett heltalsvärde. Dessa funktioner adderar, subtraherar, multiplicerar och dividerar de två argumenten om vilken funktion som anropas av användaren.
- Vi deklarerar 4 heltal för att hantera operander, operationstyp respektive resultat. Vi deklarerar också en array med fyra funktionspekare. Varje funktionspekare för matriselement tar två heltalsparametrar och returnerar ett heltalsvärde.
- Vi tilldelar och initialiserar varje arrayelement med funktionen som redan deklarerats. Till exempel kommer det tredje elementet som är den tredje funktionspekaren att peka på multiplikationsoperationsfunktionen.
- Vi söker operander och typ av operation från användaren som skrivits med tangentbordet.
- Vi kallade det lämpliga arrayelementet (Function pointer) med argument, och vi lagrar resultatet som genereras av den lämpliga funktionen.
Instruktionen int (*ope[4])(int, int); definierar arrayen av funktionspekare. Varje matriselement måste ha samma parametrar och returtyp.
Satsresultatet = ope[val](x, y); kör lämplig funktion enligt användarens val. De två inmatade heltalen är argumenten som skickas till funktionen.
Funktioner Använda void-pekare
Void-pekare används under funktionsdeklarationer. Vi använder en void * returtyp tillåter att returnera vilken typ som helst. Om vi antar att våra parametrar inte ändras när vi övergår till en funktion, deklarerar vi den som const.
Till exempel:
void * cube (const void *);
Tänk på följande 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;}
Resultat:
4 cubed is 64
Här kommer vi att diskutera programdetaljerna:
- Vi definierar och deklarerar en funktion som returnerar ett heltalsvärde och tar en adress med oföränderlig variabel utan en specifik datatyp. Vi beräknar kubvärdet för innehållsvariabeln (x) som pekas av num-pekaren, och eftersom det är en void-pekare måste vi skriva cast den till en heltalsdatatyp med en specifik notation (* datatype)-pekare, och vi returnerar kubvärdet.
- Vi deklarerar operanden och resultatvariabeln. Dessutom initierar vi vår operand med värdet "4."
- Vi anropar kubfunktionen genom att skicka operandadressen, och vi hanterar det returnerande värdet i resultatvariabeln
Fungerar pekare som argument
Ett annat sätt att utnyttja en funktionspekare genom att skicka den som ett argument till en annan funktion som ibland kallas "återuppringningsfunktion" eftersom den mottagande funktionen "ringar tillbaka den."
I rubrikfilen stdlib.h använder Quicksort-funktionen "qsort()" denna teknik som är en algoritm dedikerad för att sortera en array.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
- void *bas : void-pekare till arrayen.
- size_t num : Arrayelementets nummer.
- size_t width Elementstorleken.
- int (*compare (const void *, const void *): funktionspekare sammansatt av två argument och returnerar 0 när argumenten har samma värde, <0 när arg1 kommer före arg2 och >0 när arg1 kommer efter arg2.
Följande program sorterar en heltalsmatris från litet till stort tal med funktionen 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;}
Resultat:
13 14 48 50 52
Här kommer vi att diskutera programdetaljerna:
- Vi definierar en jämförelsefunktion som är sammansatt av två argument och returnerar 0 när argumenten har samma värde, <0 när arg1 kommer före arg2 och >0 när arg1 kommer efter arg2. Parametrarna är en void-pekare typ castad till lämplig matrisdatatyp (heltal)
- Vi definierar och initierar en heltalsmatris. Matrisstorleken lagras i NUM variabel och storleken på varje arrayelement lagras i breddvariabel med hjälp av sizeof() fördefinierad C-operatör.
- Vi kallar qsort funktion och skicka arraynamn, storlek, bredd och jämförelsefunktion som tidigare definierats av användaren för att sortera vår array i stigande ordning. Jämförelsen kommer att utföras genom att i varje iteration ta två arrayelement tills hela arrayen kommer att sorteras.
- Vi skriver ut arrayelementen för att vara säkra på att vår array är väl sorterad genom att iterera hela arrayen med för slinga.