Kao što znamo, pokazivač se koristi za pohranjivanje adrese varijable u C. Pokazivač smanjuje vrijeme pristupa varijabli. Međutim, u C-u također možemo definirati pokazivač za pohranu adrese drugog pokazivača. Takav pokazivač je poznat kao dvostruki pokazivač (pokazivač na pokazivač). Prvi pokazivač se koristi za pohranjivanje adrese varijable, dok se drugi pokazivač koristi za pohranjivanje adrese prvog pokazivača. Shvatimo to prema donjem dijagramu.
Sintaksa deklariranja dvostrukog pokazivača je dana u nastavku.
int **p; // pointer to a pointer which is pointing to an integer.
Razmotrite sljedeći primjer.
#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 }
Izlaz
address of a: d26a8734 address of p: d26a8738 value stored at p: 10 value stored at pp: 10
C primjer dvostrukog pokazivača
Pogledajmo primjer gdje jedan pokazivač pokazuje na adresu drugog pokazivača.
Kao što možete vidjeti na gornjoj slici, p2 sadrži adresu p (fff2), a p sadrži adresu brojčane varijable (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; }
Izlaz
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
P. Što će biti rezultat sljedećeg programa?
#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 }
Obrazloženje
U gornjem pitanju koristi se aritmetika pokazivača s dvostrukim pokazivačem. Definiran je niz od 6 elemenata na koji pokazuje niz pokazivača p. Niz pokazivača p pokazuje dvostruki pokazivač pp. Međutim, gornja slika daje vam kratku ideju o tome kako se memorija dodjeljuje nizu a i polju pokazivača p. Elementi p su pokazivači koji pokazuju na svaki element niza a. Budući da znamo da ime niza sadrži osnovnu adresu niza, radit će kao pokazivač i može li se vrijednost preći koristeći *(a), *(a+1), itd. Kao što je prikazano na slici , a[0] se može pristupiti na sljedeće načine.
- a[0]: to je najjednostavniji način pristupa prvom elementu niza
- *(a): budući da pohranjuje adresu prvog elementa niza, njegovoj vrijednosti možemo pristupiti korištenjem indirektnog pokazivača na njemu.
- *p[0]: ako se a[0] treba pristupiti korištenjem pokazivača p na njega, tada možemo koristiti indirektni operator (*) na prvom elementu niza pokazivača p, tj. *p[0].
- **(pp): kako pp pohranjuje osnovnu adresu niza pokazivača, *pp će dati vrijednost prvog elementa niza pokazivača koji je adresa prvog elementa niza cijelih brojeva. **p će dati stvarnu vrijednost prvog elementa niza cijelih brojeva.
Dolazeći do programa, redak 1 i 2 deklariraju relativno niz cijelih brojeva i pokazivača. Linija 3 inicijalizira dvostruki pokazivač na niz pokazivača p. Kao što je prikazano na slici, ako adresa niza počinje od 200, a veličina cijelog broja je 2, tada će niz pokazivača sadržavati vrijednosti kao što su 200, 202, 204, 206, 208, 210. Uzmimo u obzir da je osnovna adresa niza pokazivača je 300; dvostruki pokazivač pp sadrži adresu niza pokazivača, tj. 300. Linija broj 4 povećava vrijednost pp za 1, tj. pp će sada pokazivati na adresu 302.
Red broj 5 sadrži izraz koji ispisuje tri vrijednosti, tj. pp - p, *pp - a, **pp. Izračunajmo svaki od njih.
- pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1, tj. ispisat će se 1.
- pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1, tj. ispisat će se 1.
- pp = 302, *pp = 202, *(*pp) = 206, tj. ispisat će se 206.
Stoga će kao rezultat retka 5, izlaz 1, 1, 206 biti ispisan na konzoli. U retku 6 napisano je *pp++. Ovdje moramo primijetiti da će dva unarna operatora * i ++ imati isti prioritet. Dakle, po pravilu asocijativnosti, ocjenjivat će se s desna na lijevo. Stoga se izraz *pp++ može prepisati kao (*(pp++)). Budući da je pp = 302 što će sada postati 304. *pp će dati 204.
U retku 7 ponovno je napisan izraz koji ispisuje tri vrijednosti, tj. pp-p, *pp-a, *pp. Izračunajmo svaki od njih.
- pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, tj. ispisat će se 2.
- pp = 304, *pp = 204, a = 200 => *pp-a = (204 - 200)/2 = 2, tj. ispisat će se 2.
- pp = 304, *pp = 204, *(*pp) = 300, tj. 300 će biti ispisano.
Stoga, kao rezultat retka 7, izlaz 2, 2, 300 bit će ispisan na konzoli. U retku 8 napisano je +*pp. Prema pravilu asocijativnosti, ovo se može prepisati kao (++(*(pp))). Budući da je pp = 304, *pp = 204, vrijednost *pp = *(p[2]) = 206 koja će sada ukazivati na a[3].
U redu 9 ponovno je napisan izraz koji ispisuje tri vrijednosti, tj. pp-p, *pp-a, *pp. Izračunajmo svaki od njih.
- pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, tj. ispisat će se 2.
- pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, tj. ispisat će se 3.
- pp = 304, *pp = 206, *(*pp) = 409, tj. 409 će biti ispisano.
Stoga, kao rezultat retka 9, izlaz 2, 3, 409 bit će ispisan na konzoli. U retku 10 napisano je ++**pp. prema pravilu asocijativnosti, ovo se može prepisati kao, (++(*(*(pp)))). pp = 304, *pp = 206, **pp = 409, ++**pp => *pp = *pp + 1 = 410. Drugim riječima, a[3] = 410.
U retku 11 ponovno je napisan izraz koji ispisuje tri vrijednosti, tj. pp-p, *pp-a, *pp. Izračunajmo svaki od njih.
- pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, tj. ispisat će se 2.
- pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, tj. ispisat će se 3.
- U retku 8, **pp = 410.
Stoga će kao rezultat retka 9, izlaz 2, 3, 410 biti ispisan na konzoli.
Na kraju, izlaz kompletnog programa bit će dan kao:
Izlaz
1 1 206 2 2 300 2 3 409 2 3 410