Toiminnot Osoittimet C-ohjelmointiin esimerkkien kanssa

Osoittimet antavat suuria mahdollisuuksia 'C'-funktioille, jotka rajoitamme palauttamaan yhden arvon. Osoitinparametreilla funktiomme voivat nyt kรคsitellรค todellisia tietoja tietojen kopion sijaan.

Muuttujien todellisten arvojen muokkaamiseksi kutsuva kรคsky vรคlittรครค osoitteita funktion osoitinparametreille.

Toiminnot Osoittimet Esimerkki

Esimerkiksi seuraava ohjelma vaihtaa kaksi arvoa kahdesta:

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;}
}

lรคhtรถ:

m is 25, n is 100
m is 100, n is 25

Toiminnot Osoittimet Esimerkki

Ohjelma vaihtaa todelliset muuttujien arvot, koska funktio kรคyttรครค niitรค osoitteen avulla osoitin. Tรครคllรค keskustelemme ohjelmaprosessista:

  1. Ilmoitamme kahden muuttujan arvon vaihtamisesta vastaavan funktion, joka ottaa kaksi kokonaislukuosoitinta parametreina ja palauttaa minkรค tahansa arvon, kun sitรค kutsutaan.
  2. Pรครคfunktiossa julistamme ja alustamme kaksi kokonaislukumuuttujaa ('m' ja 'n') ja sitten tulostamme niiden arvot vastaavasti.
  3. Kutsumme swap()-funktiota vรคlittรคmรคllรค nรคiden kahden muuttujan osoitteet argumenteiksi et-symbolilla. Tรคmรคn jรคlkeen tulostetaan muuttujien uudet vaihdetut arvot.
  4. Tรคssรค mรครคritellรครคn swap()-funktion sisรคltรถ, joka ottaa kaksi kokonaislukumuuttujan osoitetta parametreiksi ja ilmoittaa vรคliaikaisen kokonaislukumuuttujan, jota kรคytetรครคn kolmantena tallennuslaatikkona tallentaakseen yhden arvomuuttujista, jotka asetetaan toiseen muuttujaan.
  5. Tallenna vรคliaikaismuuttujan ensimmรคisen muuttujan sisรคltรถ, jota osoittaa 'a'.
  6. Tallenna toinen b:llรค osoittama muuttuja ensimmรคiseen a:lla osoittamaan muuttujaan.
  7. Pรคivitรค toinen muuttuja (osoitti b:llรค) vรคliaikaiseen muuttujaan tallennetun ensimmรคisen muuttujan arvolla.

Toimii taulukkoparametreilla

C:ssรค emme voi vรคlittรครค taulukkoa funktiolle arvon mukaan. Sen sijaan taulukon nimi on osoitin (osoite), joten vรคlitรคmme vain taulukon nimen funktiolle, joka tarkoittaa osoittimen vรคlittรคmistรค taulukkoon.

Tarkastellaan esimerkiksi seuraavaa ohjelmaa:

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);}

lรคhtรถ:

 Total summation is 471

Tรคssรค selitรคmme ohjelmakoodin ja sen yksityiskohdat

Toimii taulukkoparametreilla

  1. Ilmoitamme ja mรครคritรคmme add_array()-funktion, joka ottaa taulukon osoitteen (osoitin) elementtinumeroineen parametreina ja palauttaa nรคiden elementtien kokonaissumman. Osoitinta kรคytetรครคn taulukon elementtien iterointiin (p[k]-merkinnรคllรค), ja kerรครคmme summauksen paikalliseen muuttujaan, joka palautetaan koko elementtitaulukon iteroinnin jรคlkeen.
  2. Ilmoitamme ja alustamme kokonaislukutaulukon, jossa on viisi kokonaislukuelementtiรค. Tulostamme kokonaissumman vรคlittรคmรคllรค taulukon nimen (joka toimii osoitteena) ja taulukon koon add_array()kutsutaan funktioksi argumenteiksi.

Funktiot, jotka palauttavat taulukon

C:ssรค voimme palauttaa osoittimen taulukkoon, kuten seuraavassa ohjelmassa:

#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);}

lรคhtรถ:

1
2
3
4
5

Ja tรครคllรค keskustelemme ohjelman yksityiskohdista

Funktiot, jotka palauttavat taulukon

  1. Mรครคrittelemme ja ilmoittamme funktion, joka palauttaa taulukon osoitteen, joka sisรคltรครค kokonaisluvun arvon eikรค ottanut argumentteja.
  2. Ilmoitamme kokonaislukuosoittimen, joka vastaanottaa funktion kutsumisen jรคlkeen rakennetun taulukon ja tulostamme sen sisรคllรถn iteroimalla koko viiden elementin taulukon.

Huomaa, ettรค osoitin, ei taulukko, on mรครคritetty tallentamaan funktion palauttama taulukko-osoite. Huomaa myรถs, ettรค kun funktiosta palautetaan paikallinen muuttuja, meidรคn on ilmoitettava se funktiossa staattiseksi.

Toimintoosoittimet

Kuten mรครคritelmรคn mukaan tiedรคmme, osoittimet osoittavat missรค tahansa muistipaikassa olevaan osoitteeseen, ne voivat osoittaa myรถs suoritettavan koodin alkuun funktioina muistissa.
Osoitin toimintoon on ilmoitettu *:lla, sen julistuksen yleinen lauseke on:

return_type (*function_name)(arguments)

Sinun on muistettava, ettรค sulut ympรคrillรค (*funktion_nimi) ovat tรคrkeitรค, koska ilman niitรค kรครคntรคjรค luulee, ettรค funktion_nimi palauttaa osoittimen paluutyypin.
Kun toimintoosoitin on mรครคritetty, se on mรครคritettรคvรค funktiolle. Esimerkiksi seuraava ohjelma mรครคrittelee tavallisen funktion, mรครคrittelee funktioosoittimen, mรครคrittรครค funktioosoittimen tavalliselle funktiolle ja sen jรคlkeen kutsuu funktiota osoittimen kautta:

#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");}

lรคhtรถ:

Hi
Hi
Hi

Toiminnot Osoittimet C:ssรค

  1. Mรครคrittelemme ja julistamme vakiofunktion, joka tulostaa Hi-tekstin k kertaa parametrien osoittaman kerran, kun funktiota kutsutaan
  2. Mรครคrittelemme osoitinfunktion (erityisen ilmoituksensa kanssa), joka ottaa kokonaislukuparametrin eikรค palauta mitรครคn.
  3. Alustamme osoitinfunktiomme Hi_funktiolla, mikรค tarkoittaa, ettรค osoitin osoittaa Hi_function().
  4. Sen sijaan, ettรค tavallinen funktio kutsuisi nauhoittamalla funktion nimeรค argumenteilla, kutsumme vain osoitinfunktiota vรคlittรคmรคllรค argumenteiksi numeron 3, ja siinรค se!

Muista, ettรค funktion nimi osoittaa suoritettavan koodin aloitusosoitteeseen, kuten taulukon nimi, joka osoittaa sen ensimmรคiseen elementtiin. Siksi ohjeet kuten function_ptr = &Hi_function ja (*funptr)(3) ovat oikein.
HUOMAA: Ei ole tรคrkeรครค syรถttรครค osoiteoperaattoria & ja vรคlioperaattoria * toimintomรครคrityksen ja toimintokutsun aikana.

Joukko funktioosoittimia

Joukko funktioosoittimia voi toimia kytkin- tai if-lauseroolina pรครคtรถksenteossa, kuten seuraavassa ohjelmassa:

#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

Tรครคllรค keskustelemme ohjelman yksityiskohdista:

Joukko funktioosoittimia

  1. Ilmoitamme ja mรครคrittelemme neljรค tehtรคvรคt jotka ottavat kaksi kokonaislukuargumenttia ja palauttavat kokonaisluvun arvon. Nรคmรค funktiot lisรครคvรคt, vรคhentรคvรคt, kertovat ja jakavat kaksi argumenttia, jotka koskevat kรคyttรคjรคn kutsumaa funktiota.
  2. Ilmoitamme 4 kokonaislukua kรคsittelemรครคn operandeja, operaatiotyyppiรค ja tulosta vastaavasti. Ilmoitamme myรถs neljรคn funktion osoittimen taulukon. Jokainen taulukkoelementin funktioosoitin ottaa kaksi kokonaislukuparametria ja palauttaa kokonaisluvun arvon.
  3. Mรครคritรคmme ja alustamme jokaisen taulukon elementin jo mรครคritetyllรค funktiolla. Esimerkiksi kolmas elementti, joka on kolmas funktioosoitin, osoittaa kertolaskutoimintoon.
  4. Haemme operandeja ja toimintotyyppiรค kรคyttรคjรคltรค, joka on kirjoitettu nรคppรคimistรถllรค.
  5. Kutsuimme sopivaa taulukkoelementtiรค (Function pointer) argumenteilla ja tallennamme sopivan funktion luoman tuloksen.

Kรคsky int (*ope[4])(int, int); mรครคrittรครค funktioosoittimien joukon. Jokaisella taulukon elementillรค on oltava samat parametrit ja palautustyyppi.
Lausunnon tulos = ope[valinta](x, y); suorittaa oikean funktion kรคyttรคjรคn valinnan mukaan. Kaksi syรถtettyรค kokonaislukua ovat funktiolle vรคlitettyjรค argumentteja.

Toiminnot tyhjien osoittimien kรคyttรคminen

Void-osoittimia kรคytetรครคn funktion mรครคrittelyissรค. Kรคytรคmme void *-palautustyyppiรค, joka sallii minkรค tahansa tyypin palauttamisen. Jos oletetaan, ettรค parametrimme eivรคt muutu siirryttรคessรค funktioon, julistetaan se const.
Esimerkiksi:

 void * cube (const void *);

Harkitse seuraavaa ohjelmaa:

#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;}

Tulos:

 4 cubed is 64

Tรครคllรค keskustelemme ohjelman yksityiskohdista:

Toiminnot tyhjien osoittimien kรคyttรคminen

  1. Mรครคrittelemme ja ilmoittamme funktion, joka palauttaa kokonaisluvun arvon ja ottaa muuttumattoman muuttujan osoitteen ilman tiettyรค tietotyyppiรค. Laskemme num-osoittimella osoittaman sisรคltรถmuuttujan (x) kuution arvon, ja koska se on tyhjรค osoitin, meidรคn on kirjoitettava se kokonaislukutietotyyppiin kรคyttรคmรคllรค tiettyรค merkintรค (* tietotyyppi) -osoitinta ja palautetaan kuution arvo.
  2. Ilmoitamme operandin ja tulosmuuttujan. Lisรคksi alustamme operandimme arvolla "4".
  3. Kutsumme kuutiofunktiota vรคlittรคmรคllรค operandiosoitteen ja kรคsittelemme palautusarvon tulosmuuttujassa

Funktioosoittimet argumentteina

Toinen tapa hyรถdyntรครค funktioosoitinta vรคlittรคmรคllรค se argumenttina toiselle funktiolle, jota joskus kutsutaan "takaisinkutsufunktioksi", koska vastaanottava funktio "kutsuu sen takaisin".
Otsikkotiedostossa stdlib.h Quicksort "qsort()" -funktio kรคyttรครค tรคtรค tekniikkaa, joka on taulukon lajitteluun tarkoitettu algoritmi.

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void *base: tyhjรค osoitin taulukkoon.
  • size_t num : Matriisielementin numero.
  • size_t width Elementin koko.
  • int (*vertaa (const void *, const void *) : funktioosoitin, joka koostuu kahdesta argumentista ja palauttaa arvon 0, kun argumenteilla on sama arvo, <0, kun arg1 tulee ennen arg2:ta ja >0, kun arg1 tulee arg2:n jรคlkeen.

Seuraava ohjelma lajittelee kokonaislukutaulukon pienestรค suureen kรคyttรคmรคllรค qsort()-funktiota:

#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;}

Tulos:

 13 14 48 50 52

Tรครคllรค keskustelemme ohjelman yksityiskohdista:

Funktioosoittimet argumentteina

  1. Mรครคrittelemme vertailufunktion, joka koostuu kahdesta argumentista ja palauttaa arvon 0, kun argumenteilla on sama arvo, <0, kun arg1 tulee ennen arg2:ta ja >0, kun arg1 tulee arg2:n jรคlkeen. Parametrit ovat tyhjiรค osoittimia, jotka on heitetty sopivaan taulukon tietotyyppiin (kokonaisluku)
  2. Mรครคrittelemme ja alustamme kokonaislukutaulukon Taulukon koko on tallennettu num muuttuja ja kunkin taulukon elementin koko tallennetaan leveysmuuttujaan kรคyttรคmรคllรค sizeof() ennalta mรครคritettyรค C-operaattori.
  3. Me kutsumme qsort funktio ja vรคlitรค kรคyttรคjรคn aiemmin mรครคrittรคmรค taulukon nimi, koko, leveys ja vertailufunktio lajitellaksesi taulukon nousevaan jรคrjestykseen. Vertailu suoritetaan ottamalla kussakin iteraatiossa kaksi taulukkoelementtiรค, kunnes koko matriisi on lajiteltu.
  4. Tulostamme taulukon elementit varmistaaksemme, ettรค taulukkomme on hyvin lajiteltu iteroimalla koko taulukko kรคyttรคmรคllรค silmukalle.

Tiivistรค tรคmรค viesti seuraavasti: