Osoitin taulukkoon | Array Pointer
Edellytys: Osoittimet Johdanto
Harkitse seuraavaa ohjelmaa:
C
#include> int> main()> {> > int> arr[5] = { 1, 2, 3, 4, 5 };> > int> *ptr = arr;> > printf> (> '%p
'> , ptr);> > return> 0;> }> |
Yllä olevassa ohjelmassa meillä on osoitin ptr joka osoittaa 0:aan th taulukon elementti. Vastaavasti voimme myös ilmoittaa osoittimen, joka voi osoittaa koko taulukkoon vain yhden taulukon elementin sijaan. Tämä osoitin on hyödyllinen, kun puhutaan moniulotteisista taulukoista.
Syntaksi:
data_type (* var_name ) [size_of_array];
Tässä:
- data_type on datatyyppi, jonka taulukko sisältää. var_nimi on osoitinmuuttujan nimi. taulukon_koko on sen taulukon koko, johon osoitin osoittaa.
Esimerkki
int (*ptr)[10];
Tässä ptr on osoitin, joka voi osoittaa 10 kokonaisluvun taulukkoon. Koska alaindeksillä on korkeampi prioriteetti kuin epäsuoralla, on epäsuoran operaattorin ja osoittimen nimi oltava sulkeiden sisällä. Tässä ptr:n tyyppi on 'osoitin 10 kokonaisluvun taulukkoon'.
Huomautus: Osoitin, joka osoittaa 0:aan th taulukon elementti ja koko taulukkoon osoittava osoitin ovat täysin erilaisia. Seuraava ohjelma näyttää tämän:
C
// C program to understand difference between> // pointer to an integer and pointer to an> // array of integers.> #include> int> main()> {> > // Pointer to an integer> > int> *p;> > > // Pointer to an array of 5 integers> > int> (*ptr)[5];> > int> arr[5];> > > // Points to 0th element of the arr.> > p = arr;> > > // Points to the whole array arr.> > ptr = &arr;> > > printf> (> 'p = %p, ptr = %p
'> , p, ptr);> > > p++;> > ptr++;> > > printf> (> 'p = %p, ptr = %p
'> , p, ptr);> > > return> 0;> }> |
Lähtö
p = 0x7fff6463e890, ptr = 0x7fff6463e890 p = 0x7fff6463e894, ptr = 0x7fff6463e8a4
Tässä, s on osoitin 0:aan th taulukon elementti arr , sillä aikaa ptr on osoitin, joka osoittaa koko taulukkoon arr .
- Perustyyppi s on int, kun perustyyppi on ptr on '5 kokonaisluvun joukko'.
- Tiedämme, että osoittimen aritmetiikka suoritetaan suhteessa kantakokoon, joten jos kirjoitamme ptr++, niin osoitin ptr siirretään eteenpäin 20 tavua.
Seuraavassa kuvassa on osoitin p ja ptr. Tummempi nuoli osoittaa osoitinta taulukkoon.
Kun poistat viittauksen osoitinlausekkeeseen, saamme arvon, johon tämä osoitinlauseke osoittaa. Osoitin taulukkoon osoittaa taulukkoon, joten kun siihen viitataan, meidän pitäisi saada taulukko, ja taulukon nimi ilmaisee perusosoitteen. Joten aina kun osoitin taulukkoon poistetaan, saamme sen taulukon perusosoitteen, johon se osoittaa.
C
// C program to illustrate sizes of> // pointer of array> #include> int> main()> {> > int> arr[] = { 3, 5, 6, 7, 9 };> > int> *p = arr;> > int> (*ptr)[5] = &arr;> > > printf> (> 'p = %p, ptr = %p
'> , p, ptr);> > printf> (> '*p = %d, *ptr = %p
'> , *p, *ptr);> > > printf> (> 'sizeof(p) = %lu, sizeof(*p) = %lu
'> ,> > sizeof> (p),> sizeof> (*p));> > printf> (> 'sizeof(ptr) = %lu, sizeof(*ptr) = %lu
'> ,> > sizeof> (ptr),> sizeof> (*ptr));> > return> 0;> }> |
Lähtö
p = 0x7fff55adbff0, ptr = 0x7fff55adbff0 *p = 3, *ptr = 0x7fff55adbff0 sizeof(p) = 8, sizeof(*p) = 4 sizeof(ptr) = 8, sizeof(*ptr) = 20
Osoitin moniulotteisiin taulukoihin
1. Osoittimet ja kaksiulotteiset taulukot
Kaksiulotteisessa taulukossa pääsemme käsiksi jokaiseen elementtiin käyttämällä kahta alaindeksiä, jossa ensimmäinen alaindeksi edustaa rivin numeroa ja toinen alaindeksi edustaa sarakkeen numeroa. 2-D-taulukon elementteihin pääsee käsiksi myös osoittimen merkinnän avulla. Oletetaan, että arr on 2-D-taulukko, voimme käyttää mitä tahansa elementtiä arr[i][j] taulukosta osoitinlausekkeen avulla **(*(arr + i) + j) . Katsotaan nyt, kuinka tämä ilmaus voidaan johtaa.
Otetaan kaksiulotteinen taulukko arr[3][4] :
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
Koska tietokoneen muisti on järjestetty lineaarisesti, 2-D-taulukkoa ei ole mahdollista tallentaa riveihin ja sarakkeisiin. Rivien ja sarakkeiden käsite on vain teoreettinen, itse asiassa 2-D-taulukko tallennetaan rivi-pääjärjestykseen, eli rivit sijoitetaan vierekkäin. Seuraava kuva näyttää, kuinka yllä oleva 2-D-taulukko tallennetaan muistiin.
Jokaista riviä voidaan pitää 1-D-taulukona, joten kaksiulotteista taulukkoa voidaan pitää kokoelmana yksiulotteisia taulukoita, jotka sijoitetaan peräkkäin. Toisin sanoen voimme sanoa, että 2-D-ulotteiset taulukot, jotka sijoitetaan peräkkäin. Joten tässä arr on 3 elementin taulukko, jossa jokainen elementti on 1-D-taulukko, jossa on 4 kokonaislukua.
Tiedämme, että taulukon nimi on vakio osoitin, joka osoittaa 0:aan th 1-D-taulukko ja sisältää osoitteen 5000. Koska arr on 'osoitin 4 kokonaisluvun taulukkoon', osoittimen aritmeettisen mukaan lauseke arr + 1 edustaa osoitetta 5016 ja lauseke arr + 2 edustaa osoitetta 5032.
Joten voimme sanoa niin arr osoittaa 0:aan th 1-D-taulukko, arr + 1 viittaa kohtaan 1 st 1-D-taulukko ja arr + 2 viittaa kohtaan 2 nd 1-D-taulukko.
Yleisesti voimme kirjoittaa:
arr + i Points to ith element of arr ->Osoittaa i. 1-D-taulukkoon>>
- Koska arr + i osoittaa kohtaan i th elementti arr , kun viittausta poistetaan, se saa i th elementti arr joka on tietysti 1-D-taulukko. Siis ilmaisu *(arr + i) antaa meille i:n perusosoitteen th 1-D-taulukko.
- Tiedämme, osoitinlauseke *(arr + i) vastaa alaindeksilauseketta arr[i] . Niin *(arr + i) joka on sama kuin arr[i] antaa meille i:n perusosoitteen th 1-D-taulukko.
- Päästäksemme 2-D-taulukon yksittäiseen elementtiin meidän pitäisi pystyä käyttämään mitä tahansa j:ää th elementti i:stä th 1-D-taulukko.
- Koska perustyyppi *(arr + i) On int ja se sisältää osoitteen 0 th elementti i:stä th 1-D-taulukko, voimme saada i:n myöhempien elementtien osoitteet th 1-D-taulukko lisäämällä kokonaislukuarvot *(arr + i) .
- Esimerkiksi *(arr + i) + 1 edustaa osoitetta 1 st elementti 1 st elementti i:stä th 1-D-taulukko ja *(arr+i)+2 edustaa osoitetta 2 nd elementti i:stä th 1-D-taulukko.
- Vastaavasti *(arr + i) + j edustaa j:n osoitetta th elementti i:stä th 1-D-taulukko. Puramalla tämän lausekkeen viittauksen saamme j:n th i:n elementti th 1-D-taulukko.
Osoittimet ja kolmiulotteiset taulukot
Siten osoitinlauseke *(*(*(arr + i ) + j ) + k) vastaa alaindeksilauseketta arr[i][j][k].
Tiedämme, että lauseke *(arr + i) on ekvivalentti arr[i]:lle ja lauseke *(*(arr + i) + j) on ekvivalentti arr[i][j]. Joten voimme sanoa, että arr[i] edustaa i:n perusosoitetta th 2-D-taulukko ja arr[i][j] edustavat j:n kantaosoitetta th 1-D-taulukko.
Esimerkki
Alla oleva esimerkki osoittaa ohjelman tulostamaan 3D-taulukon elementtejä osoittimien avulla.
C
// C program to print the elements of 3-D> // array using pointer notation> #include> int> main()> {> > int> arr[2][3][2] = {> > {> > {5, 10},> > {6, 11},> > {7, 12},> > },> > {> > {20, 30},> > {21, 31},> > {22, 32},> > }> > };> > int> i, j, k;> > for> (i = 0; i <2; i++)> > {> > for> (j = 0; j <3; j++)> > {> > for> (k = 0; k <2; k++)> > printf> (> '%d '> , *(*(*(arr + i) + j) +k));> > printf> (> '
'> );> > }> > }> > return> 0;> }> |
Lähtö
5 10 6 11 7 12 20 30 21 31 22 32
Seuraava kuva näyttää kuinka yllä olevassa ohjelmassa käytetty 3D-taulukko tallennetaan muistiin.
Osoittimen tilaaminen taulukkoon
Olettaa arr on 2-D-taulukko, jossa on 3 riviä ja 4 saraketta ja ptr on osoitin 4 kokonaisluvun taulukkoon ja ptr sisältää taulukon perusosoitteen arr .
int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}}; int (*ptr)[4]; ptr = arr;
Siitä asti kun ptr on osoitin ensimmäisen rivin 2-D-taulukkoon, eli 4 kokonaisluvun taulukkoon, ptr + i osoittaa i th rivi. Viittausten poistamisesta ptr + i , saamme i:n perusosoitteen th rivi. Päästäksesi osoitteeseen j th elementti i:stä th riville voimme lisätä j:n osoitinlausekkeeseen *(ptr + i) . Siis osoitinlauseke *(ptr + i) + j antaa osoitteen j th elementti i:stä th rivi ja osoitinlauseke **(*(ptr + i)+j) antaa j:n arvon th elementti i:stä th rivi.
Tiedämme, että osoitinlauseke *(*(ptr + i) + j) vastaa alaindeksilauseketta ptr[i][j]. Joten jos meillä on osoitinmuuttuja, joka sisältää 2-D-taulukon perusosoitteen, voimme käyttää taulukon elementtejä kaksinkertaisella merkinnällä tuo osoitinmuuttuja.
Esimerkki
C
// C program to print elements of a 2-D array> // by scripting a pointer to an array> #include> int> main()> {> > int> arr[3][4] = {> > {10, 11, 12, 13},> > {20, 21, 22, 23},> > {30, 31, 32, 33}> > };> > int> (*ptr)[4];> > ptr = arr;> > printf> (> '%p %p %p
'> , ptr, ptr + 1, ptr + 2);> > printf> (> '%p %p %p
'> , *ptr, *(ptr + 1), *(ptr + 2));> > printf> (> '%d %d %d
'> , **ptr, *(*(ptr + 1) + 2), *(*(ptr + 2) + 3));> > printf> (> '%d %d %d
'> , ptr[0][0], ptr[1][2], ptr[2][3]);> > return> 0;> }> |
Lähtö
0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 10 22 33 10 22 33