logo

C Doppio puntatore (puntatore a puntatore)

Come sappiamo, un puntatore viene utilizzato per memorizzare l'indirizzo di una variabile in C. Pointer riduce il tempo di accesso di una variabile. Tuttavia, in C, possiamo anche definire un puntatore per memorizzare l'indirizzo di un altro puntatore. Tale puntatore è noto come doppio puntatore (puntatore a puntatore). Il primo puntatore viene utilizzato per memorizzare l'indirizzo di una variabile mentre il secondo puntatore viene utilizzato per memorizzare l'indirizzo del primo puntatore. Capiamolo dal diagramma riportato di seguito.

puntatore a puntatore in c

La sintassi per dichiarare un puntatore doppio è riportata di seguito.

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

Considera il seguente esempio.

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

Produzione

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

Esempio di doppio puntatore in C

Vediamo un esempio in cui un puntatore punta all'indirizzo di un altro puntatore.

Esempio di puntatore a puntatore C

Come puoi vedere nella figura sopra, p2 contiene l'indirizzo di p (fff2) e p contiene l'indirizzo della variabile numerica (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; } 

Produzione

 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 

D. Quale sarà l'output del seguente programma?

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

Spiegazione

Domanda con doppio puntatore

Nella domanda precedente, l'aritmetica del puntatore viene utilizzata con il doppio puntatore. Viene definito un array di 6 elementi puntato da un array di puntatori p. L'array di puntatori p è puntato da un doppio puntatore pp. Tuttavia, l'immagine sopra fornisce una breve idea di come viene allocata la memoria all'array a e all'array di puntatori p. Gli elementi di p sono i puntatori che puntano a ogni elemento dell'array a. Poiché sappiamo che il nome dell'array contiene l'indirizzo di base dell'array, funzionerà come puntatore e il valore potrà essere attraversato utilizzando *(a), *(a+1), ecc. Come mostrato nell'immagine , è possibile accedere a a[0] nei seguenti modi.

  • a[0]: è il modo più semplice per accedere al primo elemento dell'array
  • *(a): poiché memorizza l'indirizzo del primo elemento dell'array, possiamo accedere al suo valore utilizzando un puntatore indiretto su di esso.
  • *p[0]: se si deve accedere a a[0] utilizzando un puntatore p, allora possiamo utilizzare l'operatore indiretto (*) sul primo elemento dell'array di puntatori p, ovvero *p[0].
  • **(pp): poiché pp memorizza l'indirizzo base dell'array di puntatori, *pp fornirà il valore del primo elemento dell'array di puntatori che è l'indirizzo del primo elemento dell'array di numeri interi. **p fornirà il valore effettivo del primo elemento dell'array di numeri interi.

Venendo al programma, le righe 1 e 2 dichiarano relativamente l'array di numeri interi e puntatori. La riga 3 inizializza il doppio puntatore all'array di puntatori p. Come mostrato nell'immagine, se l'indirizzo dell'array parte da 200 e la dimensione dell'intero è 2, allora l'array di puntatori conterrà i valori 200, 202, 204, 206, 208, 210. Consideriamo che il l'indirizzo base dell'array di puntatori è 300; il doppio puntatore pp contiene l'indirizzo dell'array di puntatori, ovvero 300. La riga numero 4 aumenta il valore di pp di 1, ovvero pp ora punterà all'indirizzo 302.

La riga numero 5 contiene un'espressione che stampa tre valori, ovvero pp - p, *pp - a, **pp. Calcoliamoli ciascuno di essi.

exclp
  • pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1, cioè verrà stampato 1.
  • pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1, cioè verrà stampato 1.
  • pp = 302, *pp = 202, *(*pp) = 206, ovvero verrà stampato 206.

Pertanto come risultato della riga 5, sulla console verrà stampato l'output 1, 1, 206. Alla riga 6 viene scritto *pp++. Qui dobbiamo notare che due operatori unari * e ++ avranno la stessa precedenza. Pertanto, secondo la regola dell'associatività, verrà valutato da destra a sinistra. Pertanto l'espressione *pp++ può essere riscritta come (*(pp++)). Poiché pp = 302 che ora diventerà 304. *pp darà 204.

Alla riga 7 viene scritta nuovamente l'espressione che stampa tre valori, ovvero pp-p, *pp-a, *pp. Calcoliamo ciascuno di essi.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, cioè verrà stampato 2.
  • pp = 304, *pp = 204, a = 200 => *pp-a = (204 - 200)/2 = 2, cioè verrà stampato 2.
  • pp = 304, *pp = 204, *(*pp) = 300, ovvero verrà stampato 300.

Pertanto, come risultato della riga 7, sulla console verrà stampato l'output 2, 2, 300. Alla riga 8 è scritto ++*pp. Secondo la regola dell'associatività, questo può essere riscritto come (++(*(pp))). Poiché, pp = 304, *pp = 204, il valore di *pp = *(p[2]) = 206 che ora punterà a a[3].

quanti frutti ci sono

Alla riga 9 viene scritta nuovamente l'espressione che stampa tre valori, ovvero pp-p, *pp-a, *pp. Calcoliamo ciascuno di essi.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, cioè verrà stampato 2.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, cioè verrà stampato 3.
  • pp = 304, *pp = 206, *(*pp) = 409, ovvero verrà stampato 409.

Pertanto, come risultato della riga 9, sulla console verrà stampato l'output 2, 3, 409. Alla riga 10 viene scritto ++**pp. secondo la regola dell'associatività, questo può essere riscritto come (++(*(*(pp)))). pp = 304, *pp = 206, **pp = 409, ++**pp => *pp = *pp + 1 = 410. In altre parole, a[3] = 410.

Alla riga 11 viene scritta nuovamente l'espressione che stampa tre valori, ovvero pp-p, *pp-a, *pp. Calcoliamo ciascuno di essi.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2, cioè verrà stampato 2.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3, cioè verrà stampato 3.
  • Alla riga 8, **pp = 410.

Pertanto come risultato della riga 9 sulla console verrà stampato l'output 2, 3, 410.

ordinamento degli elenchi java

Infine, l’output del programma completo sarà dato come:

Produzione

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