Kazalci dajejo velike možnosti funkcijam 'C', za katere smo omejeni, da vrnemo eno vrednost. S parametri kazalca lahko naše funkcije zdaj obdelajo dejanske podatke in ne kopijo podatkov.
Da bi spremenil dejanske vrednosti spremenljivk, klicni stavek posreduje naslove parametrom kazalca v funkciji.
V tej vadnici boste izvedeli-
- Primer kazalcev funkcij
- Funkcije s parametri matrike
- Funkcije, ki vrnejo matriko
- Kazalci na funkcije
- Niz kazalcev na funkcije
- Funkcije z uporabo praznih kazalcev
- Kazalci na funkcijo kot argumenti
Primer kazalcev funkcij
Naslednji program na primer zamenja dve vrednosti dve:
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;}}
Izhod:
m is 25, n is 100m is 100, n is 25
Program zamenja dejanske vrednosti spremenljivk, ker funkcija do njih dostopa po naslovu s kazalci. Tu bomo razpravljali o programskem postopku:
- Razglasimo funkcijo, ki je odgovorna za zamenjavo dveh spremenljivk, ki vzame dva celoštevilčna kazalca kot parametra in vrne katero koli vrednost, ko je poklicana.
- V glavni funkciji deklariramo in inicializiramo dve celoštevilčni spremenljivki ('m' in 'n'), nato natisnemo njihove vrednosti.
- Funkcijo swap () pokličemo tako, da naslov dveh spremenljivk posredujemo kot argumente z uporabo znaka ampersand. Po tem natisnemo nove zamenjane vrednosti spremenljivk.
- Tu definiramo vsebino funkcije swap (), ki kot parametra vzame dva naslova celoštevilčnih spremenljivk, in razglasi začasno celoštevilčno spremenljivko, ki se uporablja kot tretje polje za shranjevanje, da shranimo eno od spremenljivk vrednosti, ki bo dodana drugi spremenljivki.
- V začasno spremenljivko shranite vsebino prve spremenljivke, na katero kaže 'a'.
- Shranite drugo spremenljivko, na katero kaže b, v prvo spremenljivko, na katero kaže a.
- Posodobite drugo spremenljivko (označeno z b) za vrednost prve spremenljivke, shranjene v začasni spremenljivki.
Funkcije s parametri matrike
V C funkciji ne moremo posredovati polja po vrednosti. Medtem ko je ime polja kazalec (naslov), zato samo posredujemo ime polja funkciji, kar pomeni, da posredujemo kazalec na matriko.
Na primer upoštevamo naslednji 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);}
Izhod:
Total summation is 471
Tu bomo razložili programsko kodo z njenimi podrobnostmi
- Deklariramo in definiramo funkcijo add_array (), ki za parametre vzame naslov polja (kazalec) s številko elementov in vrne skupni nabrani seštevek teh elementov. Kazalec se uporablja za iteracijo elementov matrike (z uporabo zapisa p [k]), seštevek pa naberemo v lokalni spremenljivki, ki bo vrnjena po iteraciji celotne matrike elementov.
- Deklariramo in inicializiramo celoštevilsko matriko s petimi celoštevilskimi elementi. Celoten seštevek natisnemo tako, da v polje argumenta add_array (), ki se imenuje funkcija, posredujemo ime polja (ki deluje kot naslov) in velikost polja .
Funkcije, ki vrnejo matriko
V C lahko vrnemo kazalec na matriko, kot v naslednjem programu:
#includeint * 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);}
Izhod:
12345
In tukaj bomo razpravljali o podrobnostih programa
- Določimo in razglasimo funkcijo, ki vrne naslov matrike, ki vsebuje celoštevilčno vrednost in ni sprejela nobenega argumenta.
- Deklariramo celoštevilčni kazalec, ki prejme celotno matriko, zgrajeno po klicu funkcije, in njeno vsebino natisnemo s ponovitvijo celotne matrike s petimi elementi.
Upoštevajte, da je za shranjevanje naslova polja, ki ga vrne funkcija, definiran kazalec in ne matrika. Upoštevajte tudi, da moramo pri vrnitvi lokalne spremenljivke iz funkcije to funkcijo razglasiti kot statično.
Kazalci na funkcije
Kot že po definiciji vemo, da kazalci kažejo na naslov na katerem koli pomnilniškem mestu, lahko tudi kažejo na začetek izvedljive kode kot funkcije v pomnilniku.
Kazalec na funkcijo je prijavljen z *, splošni stavek njegove izjave je:
return_type (*function_name)(arguments)
Ne pozabite, da so oklepaji okrog (* ime_funkcije) pomembni, saj bo prevajalnik brez njih mislil, da funkcija_ime vrne kazalec vrnitve_tipa.
Po definiranju kazalca funkcije ga moramo dodeliti funkciji. Na primer, naslednji program razglasi navadno funkcijo, definira kazalnik funkcije, dodeli kazalnik funkcije navadni funkciji in nato pokliče funkcijo skozi kazalec:
#includevoid 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");}
Izhod:
HiHiHi
- Določimo in deklariramo standardno funkcijo, ki natisne Hi besedilo k krat, ki je označena s parametrom times, ko je funkcija poklicana
- Določimo funkcijo kazalca (s posebno izjavo), ki sprejme celoštevilčni parameter in ne vrne ničesar.
- Funkcijo kazalca inicializiramo s funkcijo Hi_, kar pomeni, da kazalec kaže na funkcijo Hi_ ().
- Namesto običajnega klica funkcije, tako da ime funkcije zapišemo z argumenti, pokličemo samo funkcijo kazalca tako, da kot argumente posredujemo številko 3 in to je to!
Upoštevajte, da ime funkcije kaže na začetni naslov izvršljive kode, kot je ime polja, ki kaže na njen prvi element. Zato so navodila, kot sta function_ptr = & Hi_function in (* funptr) (3), pravilna.
OPOMBA: Med dodeljevanjem funkcije in klicem funkcije ni pomembno, da vstavite operator naslova & in posrednika *.
Niz kazalcev na funkcije
Niz kazalcev funkcij lahko igra stikalo ali vlogo stavka if za odločanje, kot v naslednjem programu:
#includeint 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 48Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2624
Tu razpravljamo o podrobnostih programa:
- Izjavimo in definiramo štiri funkcije, ki vzamejo dva celoštevilčna argumenta in vrnejo celoštevilčno vrednost. Te funkcije dodajajo, odštevajo, množijo in delijo dva argumenta glede tega, katero funkcijo uporabnik pokliče.
- Deklariramo 4 cela števila, ki obravnavajo operande, vrsto operacije in rezultat. Prav tako razglasimo polje s štirimi funkcijskimi kazalci. Vsak kazalnik funkcije elementa matrike vzame dva celoštevilčna parametra in vrne celoštevilčno vrednost.
- Vsakemu elementu polja dodelimo in inicializiramo funkcijo, ki je že deklarirana. Na primer, tretji element, ki je kazalnik tretje funkcije, bo kazal na funkcijo množenja.
- Od uporabnika, ki ga vtipkate s tipkovnico, iščemo operande in vrsto operacije.
- Z argumenti smo poklicali ustrezen element matrike (kazalec funkcije) in shranili rezultat, ki ga je ustvarila ustrezna funkcija.
Navodilo int (* ope [4]) (int, int); definira polje kazalcev funkcij. Vsak element matrike mora imeti enake parametre in vrsto vrnitve.
Rezultat stavka = ope [izbira] (x, y); zažene ustrezno funkcijo glede na izbiro uporabnika. Vnesena cela števila sta argumenta, posredovana funkciji.
Funkcije z uporabo praznih kazalcev
Prazni kazalci se uporabljajo med izjavami funkcij. Za vrnitev katere koli vrste uporabljamo dovoljenja void * za vrnitev. Če predpostavimo, da se naši parametri ob prehodu na funkcijo ne spremenijo, jo razglasimo kot const.
Na primer:
void * cube (const void *);
Upoštevajte naslednji program:
#includevoid* 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
Tu bomo razpravljali o podrobnostih programa:
- Določimo in razglasimo funkcijo, ki vrne celoštevilčno vrednost in sprejme naslov nespremenljive spremenljivke brez določenega podatkovnega tipa. Izračunamo vrednost kocke spremenljivke vsebine (x), na katero kaže kazalec num, in ker je kazalec void, ga moramo vnesti v celoštevilčni podatkovni tip z uporabo določenega kazalca zapisa (* datatype) in vrnemo vrednost kocke.
- Deklariramo operand in spremenljivko rezultata. Prav tako svoj operand inicializiramo z vrednostjo "4."
- Funkcijo kocke pokličemo s predajo naslova operanda in vrnemo vrednost v spremenljivko rezultata
Kazalci na funkcijo kot argumenti
Drug način za izkoriščanje kazalca na funkcijo, tako da ga posredujemo kot argument drugi funkciji, ki se včasih imenuje "funkcija povratnega klica", ker ga sprejemna funkcija "pokliče nazaj".
V glavi datoteke stdlib.h funkcija Quicksort "qsort ()" uporablja to tehniko, ki je algoritem za razvrščanje matrike.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
- void * base: void kazalec na matriko.
- size_t num: Številka elementa matrike.
- size_t width Velikost elementa.
- int (* primerjaj (const void *, const void *): kazalnik funkcije, sestavljen iz dveh argumentov, in vrne 0, če imajo argumenti enako vrednost, <0, ko je arg1 pred arg2, in> 0, ko je arg1 za arg2.
Naslednji program s pomočjo funkcije qsort () razvrsti celoštevilsko matriko od majhnega do velikega števila:
#include#include 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
Tu bomo razpravljali o podrobnostih programa:
- Določimo funkcijo primerjave, sestavljeno iz dveh argumentov, in vrne 0, če imajo argumenti enako vrednost, <0, ko je arg1 pred arg2, in> 0, ko je arg1 pred arg2. Parametri so tip kazalcev praznih, uliven v ustrezen tip podatkovnega polja. (celo število)
- Določimo in inicializiramo celoštevilsko matriko. Velikost matrike je shranjena v spremenljivki num, velikost vsakega elementa matrike pa v spremenljivki širine z uporabo vnaprej določenega operaterja C.
- Pokličemo funkcijo qsort in posredujemo ime matrike, velikost, širino in primerjalno funkcijo, ki jo je predhodno določil uporabnik, da razvrstimo našo matriko v naraščajočem vrstnem redu. bo razvrščeno.
- Elemente matrike natisnemo, da se prepričamo, da je naše polje dobro razvrščeno s ponovitvijo celotnega polja z zanko for