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

Funkciók Mutatók Példa

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Mentse el az 'a'-val jelölt első változó tartalmát az ideiglenes változóban.
  6. Tárolja a b-vel mutatott második változót az a-val jelölt első változóban.
  7. 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

Függvények tömbparaméterekkel

  1. 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.
  2. 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

Függvények, amelyek tömböt adnak vissza

  1. 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.
  2. 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

Funkciók Mutatók C-ben

  1. 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
  2. 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.
  3. A mutató függvényünket a Hi_függvénnyel inicializáljuk, ami azt jelenti, hogy a mutató a Hi_function()-ra mutat.
  4. 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:

Funkciómutatók tömbje

  1. 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ó.
  2. 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.
  3. 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.
  4. Operandusokat és művelettípusokat keresünk a billentyűzettel begépelt felhasználótól.
  5. 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:

Funkciók üres mutatók használata

  1. 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.
  2. Deklaráljuk az operandust és az eredményváltozót. Ezenkívül az operandusunkat „4” értékkel inicializáljuk.
  3. 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:

Funkciómutatók, mint argumentumok

  1. Ö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)
  2. 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.
  3. 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.
  4. 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.