Toiminnot C-ohjelmoinnin osoittimet esimerkkien avulla

Sisällysluettelo:

Anonim

Osoittimet antavat suuria mahdollisuuksia C-funktioille, joiden palauttaminen on rajoitettua yhden arvon palauttamiseksi. Osoittimen parametrien avulla toimintomme pystyvät nyt käsittelemään todellisia tietoja tietojen kopion sijaan.

Muuttujien todellisten arvojen muokkaamiseksi kutsuva käsky välittää osoitteet funktion osoitinparametreille.

Tässä opetusohjelmassa opit-

  • Toiminnot Osoittimet Esimerkki
  • Toiminnot taulukon parametreilla
  • Toiminnot, jotka palauttavat matriisin
  • Toiminnon osoittimet
  • Joukko toiminto-osoittimia
  • Toiminnot tyhjien osoittimien avulla
  • Funktion osoittimet argumentteina

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

Tuotos:

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

Ohjelma vaihtaa muuttujien todelliset arvot, koska toiminto käyttää niitä osoitteen avulla osoitteen avulla. Tässä keskustelemme ohjelmaprosessista:

  1. Julistamme funktion, joka on vastuussa kahden muuttujan arvon vaihtamisesta, joka ottaa parametreiksi kaksi kokonaislukuosoitinta ja palauttaa minkä tahansa arvon, kun sitä kutsutaan.
  2. Pääfunktiossa ilmoitetaan ja alustetaan kaksi kokonaislukumuuttujaa ('m' ja 'n') ja tulostetaan sitten niiden arvot.
  3. Kutsumme swap () -funktion välittämällä kahden muuttujan osoitteen argumentteina käyttämällä ampersand-symbolia. Sen jälkeen tulostamme muuttujien uudet vaihdetut arvot.
  4. Tässä määritellään swap () -funktion sisältö, joka ottaa parametreiksi kaksi kokonaislukumuuttujan osoitetta ja julistamme väliaikaisen kokonaislukumuuttujan, jota käytetään kolmantena tallennuslaatikkona yhden arvomuuttujan tallentamiseksi, joka laitetaan toiseen muuttujaan.
  5. Tallenna ensimmäisen muuttujan, jota osoittaa 'a', sisältö väliaikaisessa muuttujassa.
  6. Säilytä b: n osoittama toinen muuttuja a: n osoittamaan ensimmäiseen muuttujaan.
  7. Päivitä toinen muuttuja (jota osoittaa b) väliaikaisen muuttujan ensimmäisen muuttujan arvolla.

Toiminnot taulukon parametreilla

C: ssä emme voi välittää taulukkoa arvon perusteella funktiolle. Taulukon nimi on osoitin (osoite), joten välitämme vain ryhmän nimen funktiolle, mikä tarkoittaa, että osoitin välitetään taulukolle.

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

Tuotos:

 Total summation is 471

Tässä selitämme ohjelmakoodin sen yksityiskohdilla

  1. Julistamme ja määritämme funktion add_array (), joka vie matriisiosoitteen (osoitin) elementtien numerolla parametreiksi ja palauttaa näiden elementtien kertyneen summan. Osoitinta käytetään matriisielementtien iterointiin (käyttäen p [k] -merkintää), ja keräämme summan paikalliseen muuttujaan, joka palautetaan koko elementtiryhmän iteroinnin jälkeen.
  2. Deklaroimme ja alustamme kokonaislukumatriisin viidellä kokonaislukuelementillä. Tulostamme kokonaissumman välittämällä taulukon nimen (joka toimii osoitteena) ja taulukon koon funktiolle add_array () kutsutaan argumentteina.

Toiminnot, jotka palauttavat matriisin

C: ssä voimme palauttaa osoittimen matriisiin, kuten seuraavassa ohjelmassa:

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

Tuotos:

12345

Ja tässä keskustelemme ohjelman yksityiskohdista

  1. Määritämme ja julistamme funktion, joka palauttaa taulukon osoitteen, joka sisältää kokonaisluvun, mutta ei ottanut argumentteja.
  2. Julistetaan kokonaislukuosoitin, joka vastaanottaa koko funktion kutsun jälkeen rakennetun taulukon, ja tulostamme sen sisällön iteroimalla koko viiden elementtiryhmän.

Huomaa, että osoitin, ei taulukko, on määritetty funktion palauttaman taulukko-osoitteen tallentamiseksi. Huomaa myös, että kun paikallinen muuttuja palautetaan funktiosta, meidän on julistettava se staattiseksi funktiossa.

Toiminnon osoittimet

Kuten tiedämme määritelmän mukaan, että osoittimet osoittavat osoitetta missä tahansa muistipaikassa, ne voivat myös osoittaa suoritettavan koodin alkuun muistin toimintoina.

Toimiva osoitin ilmoitetaan *: llä, sen ilmoituksen yleinen lausuma on:

return_type (*function_name)(arguments)

Sinun on muistettava, että sulkeet (* function_name) ympärillä ovat tärkeitä, koska ilman niitä kääntäjä ajattelee funktion_nimi palauttavan return_type-osoittimen.

Funktion osoittimen määrittelemisen jälkeen meidän on määritettävä se funktiolle. Esimerkiksi seuraava ohjelma julistaa tavallisen toiminnon, määrittelee toiminto-osoittimen, osoittaa toiminnon osoittimen tavalliselle toiminnolle ja kutsuu sen jälkeen funktion osoittimen kautta:

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

Tuotos:

HiHiHi

  1. Määritämme ja julistamme vakiofunktion, joka tulostaa Hi-tekstin k kertaa parametrin kertaa osoitetulla kertaa, kun toimintoa kutsutaan
  2. Määritämme osoittimen funktion (sen erityisilmoituksella), joka ottaa kokonaisluvun parametrin eikä palauta mitään.
  3. Alustamme osoitintoimintomme Hi_function-toiminnolla, mikä tarkoittaa, että osoitin osoittaa Hi_function () -kohtaan.
  4. Sen sijaan, että vakiotoiminto kutsuisi napauttamalla funktion nimeä argumenteilla, kutsumme vain osoitinfunktiota välittämällä argumenttina numeron 3, ja siinä kaikki!

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 oikeita.

HUOMAUTUS: Osoiteoperaattorin ja indirection-operaattorin * lisääminen toimintoihin ei ole tärkeää toiminnon määrityksen ja kutsun aikana.

Joukko toiminto-osoittimia

Joukko toiminto-osoittimia voi olla kytkimen tai if-lauseen rooli päätöksen tekemisessä, kuten seuraavassa ohjelmassa:

#include 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 48Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2624

Tässä keskustelemme ohjelman yksityiskohdista:

  1. Deklaroimme ja määritämme neljä funktiota, jotka ottavat kaksi kokonaislukuargumenttia ja palauttavat kokonaislukuarvon. Nämä funktiot lisäävät, vähentävät, kertovat ja jakavat kaksi argumenttia siitä, mitä toimintoa käyttäjä kutsuu.
  2. Ilmoitamme 4 kokonaislukua käsittelemään operandeja, operaatiotyyppiä ja vastaavasti. Lisäksi julistetaan neljän funktion osoittimen taulukko. Jokainen taulukkoelementin funktiosoitin vie kaksi kokonaislukuparametriä ja palauttaa kokonaisluvun arvon.
  3. Määritämme ja alustamme jokaisen taulukkoelementin jo ilmoitetulla toiminnolla. Esimerkiksi kolmas elementti, joka on kolmas funktion osoitin, osoittaa kertolaskuoperaatiofunktion.
  4. Etsimme operandeja ja operaatiotyyppiä näppäimistöltä kirjoitetulta käyttäjältä.
  5. Kutsuimme sopivan taulukkoelementin (Function pointer) argumenteilla ja tallennamme sopivan funktion tuottaman tuloksen.

Käsky int (* ope [4]) (int, int); määrittää funktiosoittimien ryhmän. Jokaisella matriisielementillä on oltava samat parametrit ja palautustyyppi.

Lausekkeen tulos = ope [valinta] (x, y); suorittaa sopivan funktion käyttäjän tekemän valinnan mukaan. Kaksi syötettyä kokonaislukua ovat funktiolle välitetyt argumentit.

Toiminnot tyhjien osoittimien avulla

Void-osoittimia käytetään toimintoilmoitusten aikana. Käytämme mitättömän * palautustyypin lupia minkä tahansa tyypin palauttamiseen. Jos oletamme, että parametrit eivät muutu siirryttäessä funktiolle, julistamme sen const: ksi.

Esimerkiksi:

 void * cube (const void *); 

Harkitse seuraavaa ohjelmaa:

#include 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:

  1. Määritämme ja julistamme funktion, joka palauttaa kokonaisluvun ja ottaa muuttamattoman muuttujan osoitteen ilman tiettyä tietotyyppiä. Laskemme numeeriosoittimen osoittaman sisältömuuttujan (x) kuutioarvon, ja koska se on tyhjä osoitin, joudumme kirjoittamaan sen kokonaislukutietotyyppiin käyttämällä tiettyä merkintää (* tietotyyppi) osoittinta, ja palaamme kuutioarvo.
  2. Julistetaan operandi ja tulosmuuttuja. Alustamme myös operandimme arvolla "4."
  3. Kutsumme kuutio-funktion välittämällä operandiosoitteen, ja käsittelemme paluuarvoa tulosmuuttujassa

Funktion osoittimet argumentteina

Toinen tapa käyttää funktion osoitinta välittämällä se argumenttina toiselle toiminnolle, jota kutsutaan joskus "takaisinsoittofunktioksi", koska vastaanottava toiminto "kutsuu sen takaisin".

Stdlib.h-otsikkotiedostossa Quicksort "qsort ()" -toiminto käyttää tätä tekniikkaa, joka on algoritmi, joka on omistettu taulukon lajittelulle.

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void * base: mitätön taulukon osoitin.
  • size_t num: Taulukkoelementin numero.
  • size_t width Elementin koko.
  • int (* vertaa (const void *, const void *): funktiosoitin, joka koostuu kahdesta argumentista ja palauttaa 0, kun argumenteilla on sama arvo, <0, kun arg1 tulee arg2: n edelle, ja> 0, kun arg1 tulee arg2: n jälkeen.

Seuraava ohjelma lajittelee kokonaisluvut pienestä suureen numeroon qsort () -toiminnon avulla:

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

Tulos:

 13 14 48 50 52 

Täällä keskustelemme ohjelman yksityiskohdista:

  1. Määritellään kahdesta argumentista koostuva vertailutoiminto ja palautetaan 0, kun argumenteilla on sama arvo, <0, kun arg1 tulee arg2: n edelle, ja> 0, kun arg1 tulee arg2: n jälkeen. Parametrit ovat tyhjät osoittimet, jotka on valettu sopivaan matriisitietotyyppiin. (kokonaisluku)
  2. Määritämme ja alustamme kokonaislukumatriisin Taulukon koko tallennetaan num- muuttujaan ja kunkin taulukkoelementin koko tallennetaan leveysmuuttujaan käyttämällä sizeof () -määriteltyä C-operaattoria.
  3. Kutsumme qsort- funktiota ja välitämme käyttäjän aiemmin määrittelemän matriisin nimen, koon, leveyden ja vertailutoiminnon lajittelemaan taulukon nousevassa järjestyksessä.Vertailu suoritetaan ottamalla kussakin iteraatiossa kaksi taulukkoelementtiä koko matriisiin asti lajitellaan.
  4. Tulostamme matriisielementit varmistaaksemme, että matriisimme on lajiteltu hyvin iteroimalla koko matriisi silmukan avulla.