Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Aiuto C++ con i puntatori.
Forum - C/C++ - Aiuto C++ con i puntatori.

Avatar
LolloVB (Normal User)
Newbie


Messaggi: 15
Iscritto: 08/01/2011

Segnala al moderatore
Postato alle 14:49
Domenica, 06/03/2011
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? ;)

PM Quote
Avatar
HeDo (Founder Member)
Guru^2


Messaggi: 2765
Iscritto: 21/09/2007

Segnala al moderatore
Postato alle 15:04
Domenica, 06/03/2011

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:

Codice sorgente - presumibilmente C/C++

  1. int a = 10;
  2. int *p = &a;
  3.  
  4. *p = 30;
  5.  
  6. 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:

Codice sorgente - presumibilmente C/C++

  1. void swap(int *p1, int *p2) {
  2.     int temp = *p1;
  3.     *p1 = *p2;
  4.     *p2 = temp;
  5. }



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:

Codice sorgente - presumibilmente C/C++

  1. // chiedo un'area di memoria grande quanto un'int all'heap
  2. int *p = new int;
  3.  
  4. [...] // Uso il valore puntato da p come una variabile int normale
  5.       // ma io so essere allocata nell'heap e non sullo stack
  6.  
  7. // rilascio la memoria
  8. delete p;



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

Codice sorgente - presumibilmente C/C++

  1. int arr[10];
  2.  
  3. cout << *arr << endl; // stampa il primo elemento
  4. cout << *(arr + 5) << endl; // stampa il sesto elemento



la gestione delle stringhe come vettori di caratteri:

Codice sorgente - presumibilmente C/C++

  1. char str[] = "Ciao a tutti belli e brutti";
  2.  
  3. // Scorro la stringa tramite puntatore
  4. char *p = str;
  5.  
  6. // Il ciclo termina quando *p è nullo, ovvero incontro il terminatore
  7. while(*p) {
  8.     [...]  // per ogni carattere
  9.     p++;
  10. }



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

Codice sorgente - presumibilmente C++

  1. class A { }
  2. class B : A { }
  3. class C : A { }
  4.  
  5. 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 :)


PM Quote
Avatar
carlduke (Member)
Pro


Messaggi: 153
Iscritto: 29/01/2011

Segnala al moderatore
Postato alle 15:22
Domenica, 06/03/2011
allora, intanto i puntatori contengono l'indirizzo di memoria di un'altra variabile.

Codice sorgente - presumibilmente C/C++

  1. int var = 5;
  2.  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

Codice sorgente - presumibilmente C/C++

  1. int var1 = 10;
  2. int *pVar = &var1; //ora pVar contiene l'indirizzo di memoria di var1
  3. 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:

Codice sorgente - presumibilmente C/C++

  1. void scambia(int a,int b){
  2.    int c = a;
  3.    a = b;
  4.    b = a;
  5.  }



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:

Codice sorgente - presumibilmente C/C++

  1. void scambia(int *a,int *b){
  2.  int c = *a;
  3.  *a = *b;
  4.  *b = c;
  5. }



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

Codice sorgente - presumibilmente Plain Text

  1. 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 il 06/03/2011 alle 15:34
PM Quote
Avatar
HeDo (Founder Member)
Guru^2


Messaggi: 2765
Iscritto: 21/09/2007

Segnala al moderatore
Postato alle 16:32
Domenica, 06/03/2011
carlduke stavo per premere delete, il tuo edit è stato provvidenziale :)

PM Quote
Avatar
LolloVB (Normal User)
Newbie


Messaggi: 15
Iscritto: 08/01/2011

Segnala al moderatore
Postato alle 17:13
Domenica, 06/03/2011
Grazie a tutti ;), adesso ho capito meglio a cosa servono e come utilizzarli, ancora grazie per l' aiuto ;)

PM Quote
Avatar
carlduke (Member)
Pro


Messaggi: 153
Iscritto: 29/01/2011

Segnala al moderatore
Postato alle 18:52
Domenica, 06/03/2011
Testo quotato

Postato originariamente da HeDo:

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



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

PM Quote