• Benvenuto in Making Videogames!
  • Dai sfogo alla tua fantasia!
  • Crea il tuo Videogioco!
Benvenuto ospite! Login Registrati




Valutazione discussione:
  • 1 voto(i) - 5 media
  • 1
  • 2
  • 3
  • 4
  • 5
[GUIDA C] I puntatori - Parte 1
#1
Salve a tutti,

oggi ho deciso di scrivere questa guida per trattare di un argomento alquanto ostico per molti: i puntatori.
Ma bando alle ciance, iniziamo subito.

Prima di tutto, iniziamo con il fare un po' di teoria.
Come tutti saprete, alla sua dichiarazione una variabile è organizzata in modo da avere un suo riferimento e un suo valore. Il riferimento di una variabile è univoco e rappresenta la locazione di memoria in cui essa risiede, in modo da poter ritrovarla quando verrà richiamata. Il valore della variabile, invece, può variare nel tempo e rappresenta il contenuto di quella cella di memoria dove essa risiede.

In sintesi, quindi, la variabile è composta da:
- Left Value (LV): riferimento della variabile o indirizzo di memoria
- Right Value (RV): contenuto di tale cella
Tali value sono regolati da specifiche particolari. Un esempio è l'assegnazione: in un'assegnazione di variabile il significato della stessa cambia a seconda della posizione rispetto al simbolo "=".

Vi porto un esempio per permettervi di capire meglio quanto detto:
Codice PHP:
.
.
.
int a/*a rappresenta il nome di una variabile di tipo int*/
.
.
.
1/*inseriamo nella cella di locazione di memoria individuata da a il valore 1, quindi abbiamo che: LV(a) <- 1*/
+3/*inseriamo nella cella di locazione di memoria individuata da a il valore di a + 3. Questo significa: LV(a) <- RV(a) + 3*/ 

Questa parte è fondamentale quindi, prima di proseguire, assicuratevi di aver assimilato il concetto.
Fatta questa parentesi sull'organizzazione delle variabili in memoria, passiamo all'oggetto vero e proprio della guida: il puntatore.

Il puntatore è una variabile non molto diversa dalle altre che normalmente utilizzate. La sua particolarità è che esso contiene l'indirizzo in memoria di un'altra variabile, ovvero il suo Left Value.
Nella pratica possiamo scrivere così:
Codice PHP:
int a 12z[10];
int *ptr;

ptr = &a/*LV(ptr) <- LV(a), ptr punta ora ad a*/
= *ptr/*LV(b) <- RV(a), b è uguale al valore destro della variabile puntata*/
*ptr 0/*RV(a) <- 0*/
ptr = &z[0]; /*LV(a) <- LV(z), ptr punta ora a z[0]*/ 

Questo semplice esempio ci fa capire molte cose.
- int a = 1: è la normale dichiarazione di una variabile di tipo intero, di identificativo a
- int *ptr: è la dichiarazione di una variabile di tipo "puntatore a" (in questo caso ad intero). La sintassi, espressa con la BNF, che definisce la dichiarazione di un puntatore è: <type> *<exp>;
- b = *ptr: l'operatore unario * è detto operatore di indirezione o di deferenzazione (indirection o deferencing). In una dichiarazione specifica che quella che lo segue sarà una variabile puntatore al tipo dichiarato. In un'espressione, applicato ad una variabile puntatore, permette di accedere alla variabile puntata dal puntatore.
- ptr = &a: è l'assegnazione al Right Value di ptr del Left Value di a. Ne deduciamo, quindi, che l'operatore unario "&" restituisce il valore sinistro della variabile cui è applicato. In questo caso, si dice che ptr punta ad a.

I puntatori sono molto utili nella programmazione, in particolar modo nelle seguenti situazioni:
- Scambio di parametri nelle funzioni
- Costruzione di Array e strutture dati più complesse (un esempio: la lista)
- Allocazione dinamica della memoria


Un altro concetto importante da chiarire è come i puntatori possono ritornare utili come argomenti di funzioni. Dal momento che nel C gli argomenti delle funzioni sono passati tutti per valore, esistono alcuni problemi difficilmente risolvibili senza l'ausilio di puntatori. Poniamo la nostra attenzione su questa funzione:

Codice PHP:
void swap(int xint y/*SBAGLIATA*/
{
   
int tmp;

   
tmp x;
   
y;
   
tmp;

Tale funzione riceve come parametri due interi e ne scambia i valori. Tutto sarebbe corretto, se non fosse che lo scambio è effettivo solo all'interno della funzione! Questo avviene a causa del passaggio per valore: i due interi passati alla funzione sono delle "copie" delle vere variabili passate come argomenti. Quindi, alla fine della funzione, esse non saranno più visibili dall'esterno.
La funzione corretta fa uso dei puntatori:
Codice PHP:
void swap(int *ptrXint *ptrY/*CORRETTA*/
{
   
int tmp;

   
tmp = *ptrX;
   *
ptrX = *ptrY;
   *
ptrY tmp;

La funzione, costruita in questo modo, viene messa in condizione di poter modificare le variabili originali, non operando più su delle copie.



Spero di essere stato abbastanza chiaro nella trattazione dell'argomento e nell'esposizione dei concetti. Per ogni informazione aggiuntiva, critiche e consigli scrivete qui di seguito utilizzando toni calmi e pacati.
La prossima guida tratterò dei puntatori, dei vettori e del modo in cui essi sono strettamente collegati.

Saluti!
 
Rispondi
#2
Grazie del contributo
 
Rispondi
#3
E' un piacere aiutare. Big Grin
 
Rispondi
  


Vai al forum:


Browsing: 1 Ospite(i)