logo

C Dvojitý ukazovateľ (ukazovateľ na ukazovateľ)

Ako vieme, ukazovateľ sa používa na uloženie adresy premennej v C. Ukazovateľ znižuje čas prístupu premennej. V C však môžeme definovať aj ukazovateľ na uloženie adresy iného ukazovateľa. Takýto ukazovateľ je známy ako dvojitý ukazovateľ (ukazovateľ na ukazovateľ). Prvý ukazovateľ sa používa na uloženie adresy premennej, zatiaľ čo druhý ukazovateľ sa používa na uloženie adresy prvého ukazovateľa. Pochopme to podľa schémy uvedenej nižšie.

ukazovateľ na ukazovateľ v c

Syntax deklarovania dvojitého ukazovateľa je uvedená nižšie.

 int **p; // pointer to a pointer which is pointing to an integer. 

Zvážte nasledujúci príklad.

 #include void main () { int a = 10; int *p; int **pp; p = &a; // pointer p is pointing to the address of a pp = &p; // pointer pp is a double pointer pointing to the address of pointer p printf('address of a: %x
',p); // Address of a will be printed printf('address of p: %x
',pp); // Address of p will be printed printf('value stored at p: %d
',*p); // value stoted at the address contained by p i.e. 10 will be printed printf('value stored at pp: %d
',**pp); // value stored at the address contained by the pointer stoyred at pp } 

Výkon

 address of a: d26a8734 address of p: d26a8738 value stored at p: 10 value stored at pp: 10 

C príklad dvojitého ukazovateľa

Pozrime sa na príklad, kde jeden ukazovateľ ukazuje na adresu iného ukazovateľa.

Príklad C pointer to pointer

Ako môžete vidieť na obrázku vyššie, p2 obsahuje adresu p (fff2) a p obsahuje adresu premennej čísla (fff4).

 #include int main(){ int number=50; int *p;//pointer to int int **p2;//pointer to pointer p=&number;//stores the address of number variable p2=&p; printf('Address of number variable is %x 
',&number); printf('Address of p variable is %x 
',p); printf('Value of *p variable is %d 
',*p); printf('Address of p2 variable is %x 
',p2); printf('Value of **p2 variable is %d 
',*p); return 0; } 

Výkon

 Address of number variable is fff4 Address of p variable is fff4 Value of *p variable is 50 Address of p2 variable is fff2 Value of **p variable is 50 

Otázka: Aký bude výstup nasledujúceho programu?

 #include void main () { int a[10] = {100, 206, 300, 409, 509, 601}; //Line 1 int *p[] = {a, a+1, a+2, a+3, a+4, a+5}; //Line 2 int **pp = p; //Line 3 pp++; // Line 4 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 5 *pp++; // Line 6 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 7 ++*pp; // Line 8 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 9 ++**pp; // Line 10 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 11 } 

Vysvetlenie

Otázka s dvojitým ukazovateľom

Vo vyššie uvedenej otázke sa aritmetika ukazovateľa používa s dvojitým ukazovateľom. Definuje sa pole 6 prvkov, na ktoré ukazuje pole ukazovateľa p. Pole ukazovateľov p ukazuje dvojitý ukazovateľ pp. Obrázok vyššie vám však poskytuje stručnú predstavu o tom, ako sa pamäť prideľuje poľu a a poľu ukazovateľov p. Prvky p sú ukazovatele, ktoré ukazujú na každý prvok poľa a. Keďže vieme, že názov poľa obsahuje základnú adresu poľa, bude fungovať ako ukazovateľ a hodnotu možno prechádzať pomocou *(a), *(a+1) atď. Ako je znázornené na obrázku , a[0] je možné získať nasledujúcimi spôsobmi.

príklad zoznamu v jave
  • a[0]: je to najjednoduchší spôsob prístupu k prvému prvku poľa
  • *(a): keďže ukladáme adresu prvého prvku poľa, môžeme pristupovať k jeho hodnote pomocou ukazovateľa smeru.
  • *p[0]: ak má byť a[0] prístupné pomocou ukazovateľa p naň, potom môžeme použiť nepriamy operátor (*) na prvom prvku poľa ukazovateľov p, t.j. *p[0].
  • **(pp): keďže pp ukladá základnú adresu poľa ukazovateľov, *pp poskytne hodnotu prvého prvku poľa ukazovateľov, ktorá je adresou prvého prvku celočíselného poľa. **p poskytne skutočnú hodnotu prvého prvku celočíselného poľa.

Keď prídeme do programu, riadky 1 a 2 deklarujú relatívne celé číslo a pole ukazovateľov. Riadok 3 inicializuje dvojitý ukazovateľ na pole ukazovateľov p. Ako je znázornené na obrázku, ak adresa poľa začína od 200 a veľkosť celého čísla je 2, potom pole ukazovateľov bude obsahovať hodnoty ako 200, 202, 204, 206, 208, 210. Uvažujme, že základná adresa poľa ukazovateľov je 300; dvojitý ukazovateľ pp obsahuje adresu poľa ukazovateľov, t. j. 300. Riadok číslo 4 zvyšuje hodnotu pp o 1, t. j. pp teraz bude ukazovať na adresu 302.

Riadok číslo 5 obsahuje výraz, ktorý vypíše tri hodnoty, t. j. pp - p, *pp - a, **pp. Vypočítajme ich každý jeden z nich.

  • pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1, t.j. vytlačí sa 1.
  • pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1, t.j. vytlačí sa 1.
  • pp = 302, *pp = 202, *(*pp) = 206, t.j. vytlačí sa 206.

Preto ako výsledok riadku 5 bude výstup 1, 1, 206 vytlačený na konzole. Na riadku 6 je napísané *pp++. Tu si musíme všimnúť, že dva unárne operátory * a ++ budú mať rovnakú prednosť. Preto sa podľa pravidla asociatívnosti bude vyhodnocovať sprava doľava. Preto výraz *pp++ možno prepísať ako (*(pp++)). Pretože pp = 302, čo bude teraz 304. *pp bude 204.

Na riadku 7 sa opäť napíše výraz, ktorý vypíše tri hodnoty, t.j. pp-p, *pp-a, *pp. Vypočítajme každý z nich.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, t.j. vytlačí sa 2.
  • pp = 304, *pp = 204, a = 200 => *pp-a = (204 - 200)/2 = 2, t.j. vytlačí sa 2.
  • pp = 304, *pp = 204, *(*pp) = 300, t.j. vytlačí sa 300.

Preto ako výsledok riadku 7 bude výstup 2, 2, 300 vytlačený na konzole. Na riadku 8 je napísané +**pp. Podľa pravidla asociativity to možno prepísať ako, (++(*(pp))). Pretože pp = 304, *pp = 204, hodnota *pp = *(p[2]) = 206, ktorá bude teraz ukazovať na a[3].

Na riadku 9 sa opäť napíše výraz, ktorý vypíše tri hodnoty, t.j. pp-p, *pp-a, *pp. Vypočítajme každý z nich.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, t.j. vytlačí sa 2.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, t.j. vytlačí sa 3.
  • pp = 304, *pp = 206, *(*pp) = 409, t.j. vytlačí sa 409.

Preto ako výsledok riadku 9 bude výstup 2, 3, 409 vytlačený na konzole. Na riadku 10 je napísané ++**pp. podľa pravidla asociativity to možno prepísať ako, (++(*(*(pp)))). pp = 304, *pp = 206, **pp = 409, ++**pp => *pp = *pp + 1 = 410. Inými slovami, a[3] = 410.

Na riadku 11 sa opäť napíše výraz, ktorý vypíše tri hodnoty, t.j. pp-p, *pp-a, *pp. Vypočítajme každý z nich.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, t.j. vytlačí sa 2.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, t.j. vytlačí sa 3.
  • Na riadku 8, **pp = 410.

Preto ako výsledok riadku 9 bude výstup 2, 3, 410 vytlačený na konzole.

Nakoniec bude výstup kompletného programu daný ako:

previesť reťazec na int

Výkon

 1 1 206 2 2 300 2 3 409 2 3 410