Oppure

Loading
06/03/11 13:49
LolloVB
Ciao a tutti :)

E' da un pò che sto studiando il C++ e sono arrivato alla spiegazione sui puntatori.

Ho cercato molto in Internet, oltre su libri di C++ cartacei, ma proprio non riesco a capire a cosa servono i puntatori e il loro utilizzo.

Qualcuno esperto sarebbe così gentile da spiegarmi in modo più semplificato il loro utilizzo? ;)
aaa
06/03/11 14:04
HeDo

i puntatori sono molto importanti, sia in C che in C++.
La loro definizione è "una variabile il cui valore è l'indirizzo di memoria di un'altra variabile"

viene molto bene il paragone con un libro. Immagina che un libro abbia una serie di pagine (ovvero dati), ogni pagina ha un numero che la identifica all'interno del libro. Un puntatore sarebbe una pagina il cui contenuto è il numero di un'altra pagina :)

Gli operatori che lavorano sui puntatori sono 2 e sono complementari:

L'operatore * (unario, da non confondere con l'operatore * della moltiplicazione che è binario) permette di ottenere il valore della variabile puntata dal puntatore, nell'esempio del libro è come estrarre il valore della pagina il cui indirizzo è scritto nel puntatore.

E l'operatore & che permette di estrarre l'indirizzo di una variabile:


int a = 10;
int *p = &a;

*p = 30;

cout << a << endl; // stampa 30, perchè ho modificato il valore di a tramite p


ma a cosa servono? perchè li hanno inventati? per molte ragioni :)

la prima è il passaggio di parametri a funzioni per riferimento, ovvero quando il corpo di una funzione è in grado di modificare il valore dei parametri:


void swap(int *p1, int *p2) {
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}



la seconda è legata alla prima, semplicemente spesso non è conveniente passare intere strutture dati pesanti a funzioni, ma è meglio passare un puntatore ad esso. Essendo un puntatore a qualsiasi cosa grande quanto una parola del sistema operativo si può mantenere la dimensione dello stack contenuta.

la terza riguarda l'allocazione dinamica:


// chiedo un'area di memoria grande quanto un'int all'heap
int *p = new int;

[...] // Uso il valore puntato da p come una variabile int normale
      // ma io so essere allocata nell'heap e non sullo stack

// rilascio la memoria
delete p;



poi per rimanere sul C like c'è la gestione degli array, che fondamentalmente sono dei puntatori:


int arr[10];

cout << *arr << endl; // stampa il primo elemento
cout << *(arr + 5) << endl; // stampa il sesto elemento



la gestione delle stringhe come vettori di caratteri:


char str[] = "Ciao a tutti belli e brutti";

// Scorro la stringa tramite puntatore
char *p = str;

// Il ciclo termina quando *p è nullo, ovvero incontro il terminatore
while(*p) {
    [...]  // per ogni carattere
    p++;
}


per passare a cose del C++ ci sono giochini di questo genere:


class A { }
class B : A { }
class C : A { }

A* obj = new B;



ti consiglio di leggere con attenzione tutto il materiale che trovi su internet, perchè gli usi dei puntatori sono veramente tanti e guarda caso tutti hanno un motivo :)

aaa
06/03/11 14:22
carlduke
allora, intanto i puntatori contengono l'indirizzo di memoria di un'altra variabile.

 int var = 5;
 int *pVar = &var;  

pVar contiene l'indrizzo di memoria di var.

L'operatore & restituisce l'indirizzo di memoria della variabile a cui è applicato.
L'operatore * restituisce il contenuto della memoria puntata dall'operando a cui è applicato, ovviamente lo puoi usare solo con i puntatori.

per chiarire ecco un esempio

int var1 = 10;
int *pVar = &var1; //ora pVar contiene l'indirizzo di memoria di var1
int var2 = *pVar;


var2 contiene il valore puntato da pVar.
Piu specificamente assegni il valore dell'indirizzo di memoria puntato da pVar convertito in int (essendo var2 un int) ovviero 10.

Le applicazioni sono numerose, un classico esempio è quello della funzione di scambio di due variabili

Esempio senza puntatori:

 void scambia(int a,int b){
   int c = a;
   a = b;
   b = a;
 }


logicamente si penserebbe che, richiamata nel main su due variabili, la funzione scambi i valori effettivi ma non è cosi; infatti la funzione crea una copia locale delle variabili e scambia i valori locali e non quelli effettivi.
La chiamata di questa funzione non ha alcun effetto.

Se invece si usano i puntatori, riscrivendo la funzione in questo modo:

void scambia(int *a,int *b){
 int c = *a;
 *a = *b;
 *b = c;
}


si scambiano gli indirizzi di memoria delle variabili, quindi la modifica persiste.

Ricordati però che se richiami la funzione su due variabili non puntatori devi scrivere cosi

scambia(&a,&b);


usando l'operatore &.

Ci sono anche altre cose da dire come i puntatori a puntatori, ma i concetti sono sempre quelli se hai capito puoi approfondirli benissimo da solo :k:



EDIT: mentre scrivero HeDo non aveva ancora risposto :rotfl:
Ultima modifica effettuata da carlduke 06/03/11 14:34
aaa
06/03/11 15:32
HeDo
carlduke stavo per premere delete, il tuo edit è stato provvidenziale :)
aaa
06/03/11 16:13
LolloVB
Grazie a tutti ;), adesso ho capito meglio a cosa servono e come utilizzarli, ancora grazie per l' aiuto ;)
aaa
06/03/11 17:52
carlduke
Postato originariamente da HeDo:

carlduke stavo per premere delete, il tuo edit è stato provvidenziale :)


:rotfl::rotfl: la calma è la virtu dei forti :asd:
aaa