Ukazovateľ na pole | Ukazovateľ poľa
Podmienka: Úvod do ukazovateľov
Zvážte nasledujúci program:
C
#include> int> main()> {> > int> arr[5] = { 1, 2, 3, 4, 5 };> > int> *ptr = arr;> > printf> (> '%p
'> , ptr);> > return> 0;> }> |
Vo vyššie uvedenom programe máme ukazovateľ ptr čo ukazuje na 0 th prvok poľa. Podobne môžeme deklarovať aj ukazovateľ, ktorý môže ukazovať na celé pole namiesto iba jedného prvku poľa. Tento ukazovateľ je užitočný, keď hovoríme o viacrozmerných poliach.
Syntax:
data_type (* var_name ) [size_of_array];
Tu:
- data_type je typ údajov, ktoré pole obsahuje. var_name je názov premennej ukazovateľa. size_of_array je veľkosť poľa, na ktoré bude ukazovateľ ukazovať.
Príklad
int (*ptr)[10];
Tu ptr je ukazovateľ, ktorý môže ukazovať na pole 10 celých čísel. Keďže dolný index má vyššiu prioritu ako nepriamy, je potrebné zadať operátor smerovania a názov ukazovateľa do zátvoriek. Tu je typ ptr „ukazovateľ na pole 10 celých čísel.
Poznámka: Ukazovateľ, ktorý ukazuje na 0 th prvok poľa a ukazovateľ, ktorý ukazuje na celé pole, sú úplne odlišné. Ukazuje to nasledujúci program:
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;> }> |
Výkon
p = 0x7fff6463e890, ptr = 0x7fff6463e890 p = 0x7fff6463e894, ptr = 0x7fff6463e8a4
Tu, p je ukazovateľ na 0 th prvok poľa arr , zatiaľ čo ptr je ukazovateľ, ktorý ukazuje na celé pole arr .
- Základný typ p je int, zatiaľ čo základný typ ptr je „pole 5 celých čísel“.
- Vieme, že aritmetika ukazovateľa sa vykonáva vo vzťahu k základnej veľkosti, takže ak napíšeme ptr++, potom ukazovateľ ptr sa posunie dopredu o 20 bajtov.
Nasledujúci obrázok ukazuje ukazovateľ p a ptr. Tmavšia šípka označuje ukazovateľ na pole.
Pri dereferencovaní ukazovateľa výrazu dostaneme hodnotu, na ktorú ukazuje tento ukazovateľ. Ukazovateľ na pole ukazuje na pole, takže pri jeho dereferencovaní by sme mali dostať pole a názov poľa označuje základnú adresu. Takže vždy, keď je ukazovateľ na pole dereferencovaný, dostaneme základnú adresu poľa, na ktoré ukazuje.
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;> }> |
Výkon
p = 0x7fff55adbff0, ptr = 0x7fff55adbff0 *p = 3, *ptr = 0x7fff55adbff0 sizeof(p) = 8, sizeof(*p) = 4 sizeof(ptr) = 8, sizeof(*ptr) = 20
Ukazovateľ na viacrozmerné polia
1. Ukazovatele a dvojrozmerné polia
V dvojrozmernom poli môžeme pristupovať ku každému prvku pomocou dvoch dolných indexov, kde prvý dolný index predstavuje číslo riadku a druhý dolný index predstavuje číslo stĺpca. K prvkom 2-D poľa je možné pristupovať aj pomocou notácie ukazovateľa. Predpokladajme, že arr je 2-D pole, môžeme pristupovať k akémukoľvek prvku arr[i][j] poľa pomocou výrazu ukazovateľa *(*(arr + i) + j) . Teraz uvidíme, ako možno tento výraz odvodiť.
Zoberme si dvojrozmerné pole arr[3][4] :
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
Keďže pamäť v počítači je organizovaná lineárne, nie je možné ukladať 2-D pole do riadkov a stĺpcov. Koncept riadkov a stĺpcov je len teoretický, v skutočnosti je 2-D pole uložené v poradí podľa riadkov, t.j. riadky sú umiestnené vedľa seba. Nasledujúci obrázok ukazuje, ako sa vyššie uvedené 2-D pole uloží do pamäte.
Každý riadok možno považovať za 1-D pole, takže dvojrozmerné pole možno považovať za kolekciu jednorozmerných polí, ktoré sú umiestnené jedno za druhým. Inými slovami, môžeme povedať, že 2-D dimenzionálne polia, ktoré sú umiestnené jeden po druhom. Takže tu arr je pole 3 prvkov, kde každý prvok je 1-D pole 4 celých čísel.
Vieme, že názov poľa je konštantný ukazovateľ, ktorý ukazuje na 0 th 1-D pole a obsahuje adresu 5000. Od arr je „ukazovateľ na pole 4 celých čísel“, podľa aritmetiky ukazovateľa bude výraz arr + 1 predstavovať adresu 5016 a výraz arr + 2 bude predstavovať adresu 5032.
Takže to môžeme povedať arr ukazuje na 0 th 1-D pole, arr + 1 poukazuje na 1 sv 1-D pole a arr + 2 poukazuje na 2 nd 1-D pole.
Vo všeobecnosti môžeme napísať:
arr + i Points to ith element of arr ->Ukazuje na to 1-D pole
- Keďže arr + i ukazuje na i th prvok arr , pri dereferencovaní dostane i th prvok arr čo je samozrejme 1-D pole. Teda výraz *(arr + i) nám dáva základnú adresu i th 1-D pole.
- Vieme, ukazovateľ ukazovateľa *(arr + i) je ekvivalentný s výrazom dolného indexu arr[i] . Takže *(arr + i) čo je rovnaké ako arr[i] nám dáva základnú adresu i th 1-D pole.
- Na prístup k jednotlivému prvku nášho 2-D poľa by sme mali mať prístup k akémukoľvek j th prvok i th 1-D pole.
- Keďže základný typ *(arr + i) je int a obsahuje adresu 0 th prvok i th 1-D poli, môžeme získať adresy nasledujúcich prvkov v i th 1-D pole pridaním celočíselných hodnôt do *(arr + i) .
- Napríklad *(arr + i) + 1 bude reprezentovať adresu 1 sv prvok 1 sv prvok i th 1-D pole a *(arr+i)+2 bude predstavovať adresu 2 nd prvok i th 1-D pole.
- Podobne *(arr + i) + j bude reprezentovať adresu j th prvok i th 1-D pole. Pri dereferencovaní tohto výrazu môžeme dostať j th prvok i th 1-D pole.
Ukazovatele a trojrozmerné polia
int arr[2][3][2] = { {{5, 10}, {6, 11}, {7, 12}}, {{20, 30}, {21, 31}, {22, 32}} }; V trojrozmernom poli môžeme pristupovať ku každému prvku pomocou troch dolných indexov. Zoberme si 3-D pole- Trojrozmerné pole môžeme považovať za pole 2-D poľa, t.j. každý prvok 3-D poľa sa považuje za 2-D pole. 3-D pole arr možno považovať za pole pozostávajúce z dvoch prvkov, kde každý prvok je 2-D pole. Názov poľa arr je ukazovateľ na 0 th 2-D pole.
Teda ukazovateľový výraz *(*(*(arr + i ) + j ) + k) je ekvivalentom dolného indexu výrazu arr[i][j][k].
Vieme, že výraz *(arr + i) je ekvivalentný arr[i] a výraz *(*(arr + i) + j) je ekvivalentný arr[i][j]. Môžeme teda povedať, že arr[i] predstavuje základnú adresu i th 2-D pole a arr[i][j] predstavuje základnú adresu j th 1-D pole.
Príklad
Nižšie uvedený príklad ukazuje program na tlač prvkov 3D poľa pomocou ukazovateľov.
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;> }> |
Výkon
5 10 6 11 7 12 20 30 21 31 22 32
Nasledujúci obrázok ukazuje, ako je 3-D pole použité vo vyššie uvedenom programe uložené v pamäti.
Subscripting ukazovateľa na pole
Predpokladajme arr je 2-D pole s 3 riadkami a 4 stĺpcami a ptr je ukazovateľ na pole 4 celých čísel a ptr obsahuje základnú adresu poľa arr .
int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}}; int (*ptr)[4]; ptr = arr;
Od r ptr je ukazovateľ na prvý riadok 2-D poľa, t. j. pole 4 celých čísel, ptr + i bude poukazovať na i th riadok. O dereferencovaní ptr + i , dostaneme základnú adresu i th riadok. Ak chcete získať prístup k adrese j th prvok i th riadok môžeme pridať j do výrazu ukazovateľa *(ptr + i) . Takže ukazovateľový výraz *(ptr + i) + j uvádza adresu j th prvok i th riadok a výraz ukazovateľa **(*(ptr + i)+j) udáva hodnotu j th prvok i th riadok.
Vieme, že ukazovateľ ukazovateľa *(*(ptr + i) + j) je ekvivalentný výrazu dolného indexu ptr[i][j]. Takže ak máme premennú ukazovateľa obsahujúcu základnú adresu 2-D poľa, potom môžeme pristupovať k prvkom poľa dvojitým indexovaním tejto premennej ukazovateľa.
Príklad
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;> }> |
Výkon
0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 10 22 33 10 22 33