Funkciók Mutatók a C programozásban példákkal
A mutatók nagy lehetőségeket adnak a 'C' függvényeknek, melyeket egy érték visszaadására korlátozunk. A mutatóparaméterekkel funkcióink mostantól tényleges adatokat dolgozhatnak fel adatok másolata helyett.
A változók aktuális értékének módosítása érdekében a hívó utasítás címeket ad át egy függvény mutató paramétereinek.
Funkciók Mutatók Példa
Például a következő program felcseréli a kettő két értékét:
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;}
}
output:
m is 25, n is 100 m is 100, n is 25
A program felcseréli a tényleges változók értékeit, mert a függvény cím használatával éri el őket mutató. Itt megbeszéljük a program menetét:
- Deklaráljuk a két változó érték felcseréléséért felelős függvényt, amely két egész mutatót vesz paraméterként, és meghívásakor tetszőleges értéket ad vissza.
- A fő függvényben deklarálunk és inicializálunk két egész változót ('m' és 'n'), majd kiírjuk az értékeket.
- A swap() függvényt úgy hívjuk meg, hogy a két változó címét argumentumként adjuk át az és jellel. Ezt követően kiírjuk a változók új felcserélt értékeit.
- Itt definiáljuk a swap() függvény tartalmát, amely két egész változó címet vesz fel paraméterként, és deklarál egy ideiglenes egész változót, amelyet harmadik tárolódobozként használunk, hogy elmentsük az egyik értékváltozót, amely a második változóba kerül.
- Mentse el az 'a'-val jelölt első változó tartalmát az ideiglenes változóban.
- Tárolja a b-vel mutatott második változót az a-val jelölt első változóban.
- Frissítse a második (b-vel jelölt) változót az ideiglenes változóba mentett első változó értékével.
Függvények tömbparaméterekkel
C-ben nem adhatunk át tömböt érték szerint egy függvénynek. Míg a tömbnév egy mutató (cím), ezért csak egy tömbnevet adunk át egy függvénynek, ami azt jelenti, hogy egy mutatót adunk át a tömbnek.
Például a következő programot vesszük figyelembe:
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);}
output:
Total summation is 471
Itt elmagyarázzuk a programkódot annak részleteivel együtt
- Deklaráljuk és definiáljuk az add_array() függvényt, amely paraméterként egy tömbcímet(mutatót) vesz az elemszámmal, és visszaadja ezen elemek összesített összegét. A mutató a tömbelemek iterálására szolgál (a p[k] jelölést használva), és az összegzést egy helyi változóban halmozzuk fel, amelyet a teljes elemtömb iterációja után adunk vissza.
- Egy öt egész elemből álló egész tömböt deklarálunk és inicializálunk. A teljes összegzést úgy nyomtatjuk ki, hogy átadjuk a tömb nevét (ami címként működik) és a tömb méretét add_array()függvénynek nevezzük argumentumként.
Függvények, amelyek tömböt adnak vissza
C-ben visszaadhatunk egy mutatót egy tömbbe, mint a következő programban:
#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);}
output:
1 2 3 4 5
És itt megbeszéljük a program részleteit
- Definiálunk és deklarálunk egy függvényt, amely egy egész számot tartalmazó tömbcímet ad vissza, és nem vett fel argumentumot.
- Deklarálunk egy egész mutatót, amely megkapja a függvény meghívása után felépített teljes tömböt, és a teljes ötelemes tömb iterálásával kiírjuk a tartalmát.
Figyeljük meg, hogy a függvény által visszaadott tömbcím tárolására nem tömb, hanem mutató van megadva. Figyeljük meg azt is, hogy amikor egy függvényből lokális változót adunk vissza, statikusként kell deklarálnunk a függvényben.
Funkciómutatók
Amint azt definícióból tudjuk, hogy a mutatók egy címre mutatnak bármely memóriahelyen, a memória függvényeiként a futtatható kód elejére is mutathatnak.
A függvényre mutató mutatót a * jellel deklarálják, a deklaráció általános utasítása:
return_type (*function_name)(arguments)
Ne feledje, hogy a körülötte lévő zárójelek (*függvény_neve) fontosak, mert ezek nélkül a fordító azt gondolja, hogy a függvény_neve a return_type mutatót adja vissza.
A függvénymutató definiálása után hozzá kell rendelnünk egy függvényhez. Például a következő program deklarál egy közönséges függvényt, meghatároz egy függvénymutatót, hozzárendeli a függvénymutatót a normál függvényhez, majd a mutatón keresztül meghívja a függvényt:
#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");}
output:
Hi Hi Hi
- Definiálunk és deklarálunk egy szabványos függvényt, amely a függvény meghívásakor k-szer kiír egy Hi szöveget, amelyet a paraméter-idő jelzi
- Definiálunk egy pointer függvényt (speciális deklarációjával), amely egy egész paramétert vesz fel, és nem ad vissza semmit.
- A mutató függvényünket a Hi_függvénnyel inicializáljuk, ami azt jelenti, hogy a mutató a Hi_function()-ra mutat.
- Ahelyett, hogy a szabványos függvény a függvény nevének argumentumokkal történő rögzítésével hívná meg, csak a mutató függvényt hívjuk meg a 3-as szám argumentumként való átadásával, és kész!
Ne feledje, hogy a függvény neve a végrehajtható kód kezdőcímére mutat, mint egy tömbnév, amely az első elemére mutat. Ezért az olyan utasítások, mint a function_ptr = &Hi_function és a (*funptr)(3) helyesek.
MEGJEGYZÉS: A funkció hozzárendelése és a funkcióhívás során nem fontos a & cím operátor és az indirekt operátor * beszúrása.
Funkciómutatók tömbje
A függvénymutatók tömbje kapcsolót vagy if utasítást játszhat a döntés meghozatalában, mint a következő programban:
#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
Itt megbeszéljük a program részleteit:
- Kijelentjük és négyet határozunk meg funkciók amelyek két egész argumentumot vesznek fel és egy egész értéket adnak vissza. Ezek a függvények összeadják, kivonják, szorozzák és elosztják a két argumentumot arra vonatkozóan, hogy melyik függvényt hívja meg a felhasználó.
- 4 egész számot deklarálunk az operandusok, a művelettípus és az eredmény kezelésére. Ezenkívül deklarálunk egy négy függvénymutatóból álló tömböt. A tömbelem minden függvénymutatója két egész szám paramétert vesz fel, és egy egész értéket ad vissza.
- Minden tömbelemet hozzárendelünk és inicializálunk a már deklarált függvénnyel. Például a harmadik elem, amely a harmadik függvénymutató, a szorzási műveleti függvényre mutat.
- Operandusokat és művelettípusokat keresünk a billentyűzettel begépelt felhasználótól.
- A megfelelő tömbelemet (Function pointer) meghívtuk argumentumokkal, és a megfelelő függvény által generált eredményt tároljuk.
Az utasítás int (*ope[4])(int, int); a függvénymutatók tömbjét határozza meg. Minden tömbelemnek azonos paraméterekkel és visszatérési típussal kell rendelkeznie.
Az állítás eredménye = ope[választás](x, y); futtatja a megfelelő függvényt a felhasználó választása szerint. A két megadott egész szám a függvénynek átadott argumentum.
Funkciók üres mutatók használata
A funkciódeklaráció során üres mutatókat használunk. A void * visszatérési típust használjuk, amely lehetővé teszi bármilyen típusú visszaküldést. Ha feltételezzük, hogy a paramétereink nem változnak, amikor egy függvénynek átadunk, akkor azt const-ként deklaráljuk.
Például:
void * cube (const void *);
Fontolja meg a következő programot:
#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;}
Eredmény:
4 cubed is 64
Itt megbeszéljük a program részleteit:
- Egy olyan függvényt definiálunk és deklarálunk, amely egész értéket ad vissza, és egy változtathatatlan változó címét veszi fel meghatározott adattípus nélkül. Kiszámoljuk a tartalomváltozó (x) kockaértékét, amelyet a num pointer mutat, és mivel ez egy void pointer, ezért egy adott jelölésű (* adattípus) mutató segítségével be kell gépelnünk egy egész adattípusba, és visszaadjuk. a kocka értékét.
- Deklaráljuk az operandust és az eredményváltozót. Ezenkívül az operandusunkat „4” értékkel inicializáljuk.
- A kocka függvényt az operandus címének átadásával hívjuk meg, és az eredmény változóban kezeljük a visszatérő értéket
Funkciómutatók, mint argumentumok
Egy másik módja a függvénymutató kihasználásának, ha argumentumként adjuk át egy másik függvénynek, amelyet néha „visszahívási függvénynek” neveznek, mivel a fogadó függvény „visszahívja”.
Az stdlib.h fejlécfájlban a Quicksort „qsort()” függvény ezt a technikát használja, amely egy tömb rendezésére szolgáló algoritmus.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
- void *alap: érvénytelen mutató a tömbre.
- size_t num : A tömb elemszáma.
- size_t width Az elem mérete.
- int (*összehasonlítás (const void *, const void *) : a függvénymutató két argumentumból áll, és 0-t ad vissza, ha az argumentumok értéke azonos, <0-t, ha az arg1 az arg2 elé kerül, és >0-t, ha az arg1 az arg2 után következik.
A következő program a qsort() függvény segítségével rendezi az egész tömböt kicsitől a nagyig:
#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;}
Eredmény:
13 14 48 50 52
Itt megbeszéljük a program részleteit:
- Összehasonlító függvényt definiálunk, amely két argumentumból áll, és 0-t ad vissza, ha az argumentumok azonos értékűek, <0-t, ha az arg1 az arg2 elé kerül, és >0-t, ha az arg1 az arg2 után következik. A paraméterek üres mutató típusúak, amelyek a megfelelő tömb adattípusba vannak öntve (egész szám)
- Egész tömböt definiálunk és inicializálunk A tömb mérete a num változó, és az egyes tömbelemek mérete a szélességi változóban tárolódik a sizeof() előre meghatározott használatával C operátor.
- Hívjuk a qsort függvényt, és adja át a felhasználó által korábban meghatározott tömb nevét, méretét, szélességét és összehasonlító függvényét, hogy a tömbünket növekvő sorrendbe rendezze. Az összehasonlítás úgy történik, hogy minden iterációban két tömbelemet veszünk, amíg a teljes tömb meg nem lesz rendezve.
- Kinyomtatjuk a tömb elemeit, hogy megbizonyosodjunk arról, hogy a tömb jól van rendezve a teljes tömb iterációjával hurokhoz.







