Guarda questi erano i miei vecchi appunti sui puntatori del corso di programmazione ...è possibile che vi sia qualche str... ma bene o male dovrebbe essere tutto corretto.

Introducendo le variabili abbiamo detto che ad ognuna di queste viene associata un’area di memoria, alla quale è dato un nome, grande abbastanza per contenere il tipo di dato dichiarato, collocata automaticamente dal compilatore in una parte della RAM. La posizione di quella variabile nella RAM è detto indirizzo. Ad ogni variabile perciò il compilatore associa due valori: il valore in essa contenuta ed il suo indirizzo, cioè la sua posizione in memoria.

Anche un puntatore è una variabile, ma contiene un valore che non rappresenta un dato di un
particolare tipo, bensì un indirizzo. In altre parole, una variabile contiene un valore del tipo della dichiarazione, mentre un puntatore contiene l'indirizzo, cioè la posizione in memoria, di una variabile che a sua volta contiene un dato del tipo della dichiarazione.

Indipendentemente dal tipo di valore puntato lo spazio occupato da un puntatore è 16bit, ovvero 2byte, lo spazio cioè di un unsigned int. Un puntatore infatti occupa sempre lo spazio necessario a contenere l'indirizzo del dato puntato, e non il tipo di dato.

La sintassi della dichiarazione è la medesima di una variabile normale, con l’unica differenza che al nome va anteposto un *. Ad esempio double *alpha è la dichiarazione di un puntatore di nome alpha ad un double. Mediante l’operatore & è invece possibile conoscere l’indirizzo di una variabile e, certo, anche di un puntatore visto che si tratta pur sempre di una variabile. E’ quindi lo strumento attraverso il quale non solo potremo conoscere l’indirizzo di memoria della variabile x ma mediante il quale assegnamo l’indirizzo di una variabile ad un puntatore.

Dati:
unsigned x = 5, *myPointer = &x;

L'indirizzo di memoria di x è esprimibile in questi modi:
printf("\n%X", &x);
printf("\n%X", myPointer);
printf("\n%X", *&myPointer);
printf("\n%X", &*myPointer);

Il valore di x si esprime cosi:
printf("\n%d", x);
printf("\n%d", *myPointer);

Così si modifica x:
x = y;
*myPointer = y;

Che significato ha l’espressione **myPointer?
Nessuno. *myPointeresprime il valore memorizzato all’indirizzo puntato. Applicare una indirezione a tale valore non ha senso perchè il contenuto di x non è un indirizzo.

E l’espressione *x?
La risposta è uguale alla precedente. Scrivere *x comporta lo stesso errore che scrivere **myPointer.
Il contenuto di x non è un indirizzo.

Cosa restituisce &&x?
Restituisce un errore in compilazione. Infatti &x rappresenza l’indirizzo, ma che senso ha parlare dell’indirizzo di un indirizzo?

E l’espressione &&myPointer?
Anche questa è un’espressione incorretta. Un puntatore è sempre una variabile, quindi il discorso è lo stesso appena fatto per &&x.

Cosa accade se si esegue myPointer=0x24A6?
Si assegna un nuovo indirizzo di memoria a *myPointer, il quale ora punterà a ciò che si trova a quell’indirizzo e non più a x.

E se si esegue &myPointer= 0xAF2B?
Si ottiene un errore. Infatti l’indirizzo di punt non può essere modificato a mano, in quanto stabilito dal compilatore. E’ possibile solo stabilire a quale indirizzo punta.


Un puntatore è una variabile che contiene un indirizzo.
E’ perciò lecito fare uso di puntatori che puntano ad altri puntatori, che come tutte le variabili hanno un loro indirizzo.

La dichiarazione è, ad esempio, char **myPunt;
**myPunt non punta direttamente ad un char, ma ad un puntatore a char.

#include <stdlib.h>
#include <stdio.h>

void main(){

int x = 5, *myPunt, **MyPuntPunt;
myPunt = &x;
MyPuntPunt = &myPunt;

printf("%X\t%X\t%X\t%X", &x, myPunt, &myPunt, MyPuntPunt);
printf("\n%d\t%d\t%d", x, *myPunt, **MyPuntPunt);
}

myPunt ha l'indirizzo di memoria di x;
MyPuntPunt ha quello di MyPunt.
myPunt punta al valore di x.
MyPuntPunt punta al valore di myPunt che punta a quello di x, quindi tutti e tre puntano allo stesso.

Col primo printf stampiamo a video quattro indirizzi
di memoria. Innanzitutto un ulteriore chiarimento: una variabile ha due proprietà: un indirizzo di memoria ed un valore. Un puntatore è una variabile particolare che ha un proprio indirizzo ma come valore un indirizzo di un’altra variabile.

Sappiamo che &x restituisce l’’indirizzo di x.
Abbiamo appena detto che il valore di un puntatore è l’indirizzo di una variabile. Stampando a video quindi il valore di myPunt otteniamo l’indirizzo di x di nuovo.

&myPunt è un puntatore, e come tale è una variabile con un proprio indirizzo di memoria. Eccolo...
MyPuntPunt, che è a sua volta un puntatore (a puntatore!) ha un suo indirizzo, e come valore l’indirizzo di una variabile (nel caso una variabile di tipo puntatore). Il suo valore è perciò l’indirizzo del puntatore myPunt.

Col secondo printf() stampiamo il valore di x.
Stampiamo poi il valore cui punta *myPunt. A che valore punta? A quello contenuto nell’indirizzo di memoria puntato, ovvero a x. Stampa quindi x.
**MyPuntPunt punta a *myPunt che a sua volta punta a x. Punta cioè al valore contenuto nell’indirizzo di memoria di *myPunt, che a sua volta punta a quello contenuto all’indirizzo di x.