domenica 4 novembre 2012

Piccolo tutorial sul linguaggio C - i puntatori in C


Uno dei meccanismi più potenti e, allo stesso tempo, più insidiosi del C è l'uso dei puntatori. Un puntatore è una variabile, quindi un contenitore di dati, che, invece che contenere il dato di interesse, contiene il valore numerico dell'indirizzo di memoria del dato di interesse. Per fare un po di chiarezza su questo argomento, commentiamo insieme il programma di esempio riportato qui a sinistra. Come abbiamo già visto in un post precedente, utilizziamo anche una rappresentazione grafica stilizzata della memoria fisica del computer riportata nella figura qui sotto.
  • t=T0, vediamo un frammento della memoria indisturbato;Immaginando di poter vedere la memoria fisica in 4 istanti di tempo consecutivi, abbiamo:
  • t=T1, vediamo che il compilatore ha assegnato alle variabili i e iP rispettivamente le locazioni di memoria 1980 e 1982;
  • t=T2, la variabile i di tipo intè stata inizializzata la variabile i con il valore 13;
  • t=T3, la variabile iP di tipo puntatore a int è stato  inizializzata con l'indirizzo (nell'esempio pari a 1980) della variabile int i mediante l'operatore unario &.
  • t=T4, l'incremento di uno del valore puntato da iP ha incrementato il valore della variabile i.
Possiamo trarre alcune regole di buona programmazione da questo piccolo esempio? Certo che si. Eccole:

  1. un puntatore dopo essere stato dichiarato punta ad una locazione di memoria casuale.
  2. come conseguenza della prima regola, è importante inizializzare un puntatore prima di utilizzarlo
  3. per inizializzare correttamente un puntatore è necessario prima creare o avere uno spazio di memoria adatto a contenere il tipo di dato puntato e/o il dato di interesse. Nel nostro caso abbiamo assegnato a iP l'indirizzo della variabile di tipo int  creata dal compilatore con la dichiarazione di i.
Qualunque  violazione di una delle tre regole qui sopra porta ad una inconsistenza non segnalabile dal compilatore e quindi a comportamenti non prevedibili e sicuramente errati del programma che la contiene.
Il tipo di rappresentazione grafica della memoria utilizzato in questo post non è rigoroso, come molti potranno eccepire, ma spero che sia servito a chiarire l'uso dei puntatori. In genere, quando si lavora con i puntatori, può essere d'aiuto utilizzare un'altro tipo di rappresentazione grafica a "scatole e frecce", come quella della figura qui in basso. In particolare, nel nostro caso si ha:

  • t=T1, i e iP sono due scatole contenenti dati random;
  • t=T2, iP contiene ancora un dato random, mentre i è stato inizializzato a 13;
  • t=T3, iP "punta" a i dopo che è stato inizializzato mediante l'operatore & con l'indirizzo fisico di i;
  • t=T4, iP "punta" a i mediante l'operatore di defererenziazione * e l'incremento applicato a questo è applicato in realtà alla scatola che contiene i. In questo caso si dice che i e ip* condividono la stessa scatola o dato di interesse.

Nessun commento:

Posta un commento