Vai al contenuto

cos'è un puntatore?


Messaggi raccomandati

ragazzi, qualcuno di voi mi saprebbe spiegare in termini comprensibili cos'è un puntatore?

ho capito che un puntatore è una specie di variabile speciale in grado di contenere l'indirizzo di memoria di un altra variabile (correggetemi se sbaglio), e attraverso le istruzioni * e & si può modificare. & serve a dargli l'indirizzo di un oggetto, * serve a fargli puntare ad un oggetto (?).

inoltre vorrei capire che utilità può avere una variabile del genere. in parole povere: a che serve? quando lo utilizzo?

To Alcohol! The cause of - And solution to - All life' s problems

(Homer J. Simpson)

Link al commento
Condividi su altri siti

Come dici tu il puntatore è una variabile che anziché contenere un valore, contiene l'indirizzo esadecimale di una porzione di memoria che contiene un valore. Poi dipende in che ambito vuoi sapere le spiegazioni, se intendi nella programmazione in obj-c tieni presente che tutti gli oggetti NextStep (o quasi) vanno dichiarati come puntatori.

La loro utilità in generale consiste nel poter accedere ad una variabile, teoricamente da qualunque parte del codice sapendo l'indirizzo di memoria, senza accedere dirattamente alla variabile. Se vuoi ti faccio degli esempi.

Link al commento
Condividi su altri siti

eh si, un esempio sarebbe proprio utile :ghghgh: e potresti spiegarmi bene cosa significa puntare ad un oggetto? io ho una vaga idea in testa, ma non penso sia esatta del tutto. per quanto ho capito un puntatore quando punta a qualcosa prende lo stesso valore dell'oggetto a cui punta (esempio x=5, il puntatore che punta a x vale 5). un puntatore può essere utilizzato in tutte le operazioni matematiche al pari di una qualsiasi variabile. un puntatore che viene modificato (es. puntatore++) va a modificare anche il valore della variabile a cui punta.

se tutto questo che ho scritto è esatto, allora la mia domanda è: perchè mai complicarsi la vita creando un puntatore quando si può agire direttamente e più semplicemente sulla variabile?

per capirci meglio ho messo in grassetto le domande :ghghgh:

To Alcohol! The cause of - And solution to - All life' s problems

(Homer J. Simpson)

Link al commento
Condividi su altri siti

Il puntatore serve essenzialmente per poter lavorare con la gestione della memoria ad un livello superiore, inoltre con i puntatori si possono effettuare alcune operazioni impossibili senza il loro ausilio ed infine i puntatori sono importanti perché in realtà anche se non lo sai ogni cosa è un puntatore, questo almeno per quanto riguarda il C (utilizzi i vettori? Bene quelli sono dei puntatori :ghghgh:).

Un esempio pratico lo si ha con l'utilizzo delle function.

Se hai le hai già studiate saprai bene che le chiamate che si effettuano in C vengono effettuate per valore e non per riferimento, questo vuol dire che se tu volessi modificare effettivamente il contenuto di una variabile passando nel modo standard la variabile e cioè così:

int miafunzione(int x) {
   x = x + 1;
   return x;
}

var = 5;
miafunzione(var);

La variabile var soltanto all'interno della funzione miafunzione avrà cambiato valore in 6 e quindi con una stampa per tuo stupore non otterresti 6 bensì 5. Questo poiché la funzione non ha lavorato con l'indirizzo di var e cioè con il suo puntatore ed indirizzo, ma con una sua copia passata per valore (appunto) in memoria al momento della chiamata.

Quindi se io volessi cambiare effettivamente il valore di var dovrei utilizzare i puntatori in questo modo:

int miafunzione(int * x) {
   *x = *x + 1;
   return *x;
}

var = 5;
miafunzione(var);

Ecco spiegato uno dei motivi per cui utilizzare i puntatori.

Comunque non crucciarti più di tanto i puntatori agli inizi sono uno dei concetti più ostici da dover affrontare è normale che ora tu non riesca a comprenderli del tutto.

Skype: dadspecial | My Blog: JollyChar

Link al commento
Condividi su altri siti

eh si, un esempio sarebbe proprio utile :ghghgh: e potresti spiegarmi bene cosa significa puntare ad un oggetto? io ho una vaga idea in testa, ma non penso sia esatta del tutto. per quanto ho capito un puntatore quando punta a qualcosa prende lo stesso valore dell'oggetto a cui punta (esempio x=5, il puntatore che punta a x vale 5). un puntatore può essere utilizzato in tutte le operazioni matematiche al pari di una qualsiasi variabile. un puntatore che viene modificato (es. puntatore++) va a modificare anche il valore della variabile a cui punta.

se tutto questo che ho scritto è esatto, allora la mia domanda è: perchè mai complicarsi la vita creando un puntatore quando si può agire direttamente e più semplicemente sulla variabile?

per capirci meglio ho messo in grassetto le domande :ghghgh:

Oltre a quotare quanto detto da DaD, aggiungo che l'utilizzo di puntatori è indispensabile per la programmazione ad oggetti (polimorfismo in primis).

Poi.. due commenti su quello che hai scritto:

"per quanto ho capito un puntatore quando punta a qualcosa prende lo stesso valore dell'oggetto a cui punta (esempio x=5, il puntatore che punta a x vale 5)."

No. Il puntatore non vale 5. Il puntatore vale l'indirizzo di memoria di x.

"un puntatore può essere utilizzato in tutte le operazioni matematiche al pari di una qualsiasi variabile. un puntatore che viene modificato (es. puntatore++) va a modificare anche il valore della variabile a cui punta."

No. puntatore++ no incrementa x, ma incrementa l'indirizzo. Questo significa che se stavi lavorando su vettori potresti avere un indirizzo con qualche significato, altrimenti di sicuro stai puntando in una locazione sbagliata.

Link al commento
Condividi su altri siti

prima di tutto vorrei ringraziare DaD, finalmente inizio a capirci qualcosa :ghghgh:

poi, rispondendo a fra.makaveli: se scrivendo puntatore++ si aumenta l'indirizzo di memoria, per aumentare di valore l'oggetto bisogna scrivere puntatore=puntatore+1?

e poi un altra domanda: ho letto questa cosa:

float a[5][4];

float *p , *p1;

L’operazione:

p = a[4][0]; non è lecita perché a[4][0] non è un indirizzo

l’operazione corretta è p = &a[4][0]; oppure p = a[4];

Inoltre con p = a[4]; ed p1 = a[3]; avremo che p - p1 vale 4;

mi spieghereste che cambia tra p=a[4][0] e p=a[4]; e soprattutto mi spieghereste l'ultima affermazione? perhè mai dovrebbe valere 4? ho anche cercato di scrivere questo piccolo codice su x code, ma quando scrivo l'operazione p=p-p1 mi dice invalid conversion from long int (?) to float. da dove è uscito questo long int?

To Alcohol! The cause of - And solution to - All life' s problems

(Homer J. Simpson)

Link al commento
Condividi su altri siti

prima di tutto vorrei ringraziare DaD, finalmente inizio a capirci qualcosa :)

poi, rispondendo a fra.makaveli: se scrivendo puntatore++ si aumenta l'indirizzo di memoria, per aumentare di valore l'oggetto bisogna scrivere puntatore=puntatore+1?

e poi un altra domanda: ho letto questa cosa:

float a[5][4];

float *p , *p1;

L’operazione:

p = a[4][0]; non è lecita perché a[4][0] non è un indirizzo

l’operazione corretta è p = &a[4][0]; oppure p = a[4];

Inoltre con p = a[4]; ed p1 = a[3]; avremo che p - p1 vale 4;

mi spieghereste che cambia tra p=a[4][0] e p=a[4]; e soprattutto mi spieghereste l'ultima affermazione? perhè mai dovrebbe valere 4? ho anche cercato di scrivere questo piccolo codice su x code, ma quando scrivo l'operazione p=p-p1 mi dice invalid conversion from long int (?) to float. da dove è uscito questo long int?

Allora...

Per aumentare effettivamente il valore e non l'indirizzo, devi utilizzare l'operatore di deferenziazzione star *, quindi devi scrivere;

*puntatore++;

Poi per quanto riguarda p = a[4][0] e p = a[4]; le cose cambiano poichè la prima assegnazione si riferisce esplicitamente ad un valore puntato dalla matrice, mi spiego meglio:

Come ti ho detto prima anche i vettori in C sono dei puntatori, questo perché scrivere int a[] ed int *a in C equivale a fare la stessa operazione.

Un vettore non è altro che un puntatore che punta ad un determinato indirizzo dal quale è possibile spostarsi tramite l'incremento dell'indirizzo base (cioè &a) alle caselle di memoria succesive, ossia scrivere:

a[i];

ed

*(a+i);

È la stessa ed identica cosa. Infatti puoi utilizzare tutte e due le notazioni con i vettori il risultato non cambierà, perché non hai fatto altro che dire ad a di spostarsi alla cella di memoria i.

Adesso tornando a noi, possiamo arrivare alla semplice conclusione che se un vettore è in realtà un puntatore una matrice non può essere altro che un puntatore di puntatori è cioè:

 **p;

Quindi come facciamo ad accedere all'indirizzo base della nostra matrice ed assegnarlo ad un nuovo puntatore? Semplice basterà scrivere;

a = &p[0];

Ma visto che p[0] è già di per se un indirzzo e non un valore (poichè i vettori sono puntatori, vedi quello che ho scritto prima se non hai capito) ci basterà scrivere;

a = p[0];

Ed avremo che il nostro puntatore a che punta all'indirizzo base della nostra matrice. Detto questo è semplice intuire perché p = a[4][0] non è un'operazione ammissibile. Siccome a[4][0] non è un indirizzo, besnì con quella espressione si punta effettivamente al valore contenuto nelle cella della matrice ed il puntatore nella sua assegnazione vuole solo un indirizzo, è banale che per poter assegnare l'indirizzo di memoria di quella cella della matrice al puntatore tu debba usare l'operatore di referenziazzione ampersand & e quindi debba scrivere come detto poco sopra.

Inoltre per quanto riguarda la faccenda:

p = a[4]; 
p1 = a[3]; 
p = p - p1;

Che il risultato faccia 4 ti da ancor di più la certezza che ogni cosa è un puntatore, perché se ci pensi bene, a[4] - a[3], sapendo che sono dei puntatori agli indirizzi delle rispettive celle di memoria, il risultato non può essere altro che un'altro indirizzo, siccome questa è un'operazione matematica il risultato è 4 poichè conta i byte effettivi di spostamento da una cella all'altra.

Può sembrare complicato ma puoi provare questo codice cambiando i valori di p = a[x]; e vedere che stampe ti escono fuori, sarà tutto più chiaro :ghghgh:

#include <stdio.h>

int main(void) {
  int a[4][4] = {0};
  int *p, *p1;
  p = a[4];
  p1 = a[0];
  printf("%d - %d - %d\n", sizeof(p), sizeof(p1), p - p1);
  return 0;
}

Skype: dadspecial | My Blog: JollyChar

Link al commento
Condividi su altri siti

ok, per quanto riguarda la prima parte direi di aver capito tutto, anzi la mia domanda ora mi sembra abbastanza banale :)

invece per quanto riguarda la seconda parte diciamo che l'ho capita solo al livello teorico. ho capito che l'operazione p-p1 agisce sugli indirizzi, ma resta il fatto che non riesco a spiegarmi il risultato. se conta i byte di differenza il risultato non dovrebbe essere 16 se p=4 e p1=5? se non sbaglio il tipo int è contenuto in 16 bit.

inoltre nel codice che mi hai dato mi da l'errore "format '%d' expects type int, but argument 2 has type 'long unsigned int'" perchè??

comunque sia, grazie dell'aiuto :ghghgh:

To Alcohol! The cause of - And solution to - All life' s problems

(Homer J. Simpson)

Link al commento
Condividi su altri siti

ok, per quanto riguarda la prima parte direi di aver capito tutto, anzi la mia domanda ora mi sembra abbastanza banale ;)

invece per quanto riguarda la seconda parte diciamo che l'ho capita solo al livello teorico. ho capito che l'operazione p-p1 agisce sugli indirizzi, ma resta il fatto che non riesco a spiegarmi il risultato. se conta i byte di differenza il risultato non dovrebbe essere 16 se p=4 e p1=5? se non sbaglio il tipo int è contenuto in 16 bit.

inoltre nel codice che mi hai dato mi da l'errore "format '%d' expects type int, but argument 2 has type 'long unsigned int'" perchè??

comunque sia, grazie dell'aiuto :)

Non è un errore ma un warring. Se modifichi con %ld non avrai più nessun avviso, questo perché sei su di una macchina a 64 byte e quindi i puntatori (se non erro) sono visti come long int cioè 8 byte.

Non ho capito che perplessità hai sugli indirizzi spiegati meglio.

Skype: dadspecial | My Blog: JollyChar

Link al commento
Condividi su altri siti

diciamo ceh non ho capito come si prevede quel risultato. se non sbaglio, con a[4][5], p=a[4], e p1=a[5], il risultato è 20. matematicamente parlando, quali sono i termini che hanno dato questo risultato?

a proposito del warning, spesso e volentieri mi capita questo "errore", come fare per evitarlo? se ignoro quell'avviso, c'è la possibilità che ci sia un errore di calcolo, nel senso che stampa a video un valore diverso da quello che gli ho chiesto?

To Alcohol! The cause of - And solution to - All life' s problems

(Homer J. Simpson)

Link al commento
Condividi su altri siti

Scusami se ti rispondo solo ora ma non avevo visto il messaggio.

Comunque probabilmente ti ha confuso il sizeof().

#include <stdio.h>

int main(void) {
  int a[4][4] = {0};
  int *p, *p1;
  p = a[4];
  p1 = a[0];
  printf("%d - %d - %d\n", p, p1, p - p1);
  return 0;
}

Eseguilo e vedrai che la sottrazione non è altro che la sottrazione delle celle di memoria, quindi dimunendo il primo puntatore con il secondo si ha la distanza (in termini di byte) che decade fra l'indice p e l'indice p+1, tutto qui.

I warring sono dovuti al fatto che %d non è un codice formato adeguato per degli indirizzi, per cui se sostituisci il %d con un %p (codice formato per indirizzi) non avrai più avvisi post compilazione.

printf("%p - %p - %ld\n", p, p1, p-p1);

Skype: dadspecial | My Blog: JollyChar

Link al commento
Condividi su altri siti

non c'è problema :shock: diciamo che ora ho capito! :fiorellino: la differenza dovrebbe essere di 4 unità. i due indirizzi che sono usciti sono 1606416352 - 1606416288 = 64. poichè int occupa 16 bit, si ha 16*4=64 giusto?

e poi, dato che ci troviamo sull'argomento.. ti sarei grato se mi scriveresti una lista con tutti gli operatori di conversione e la loro funzione? (si chiamano così vero? se non si chiamano così, per intenderci, i %d, %p, %f %x ecc.)

To Alcohol! The cause of - And solution to - All life' s problems

(Homer J. Simpson)

Link al commento
Condividi su altri siti

si va avanti! :fiorellino: mi manca ancora tanto tanto tanto eh?

a proposito di google, si, hai ragione. il fatto è che ogni volta che ho cercato una spiegazione a qualcosa che non capivo su google mi confondeva sempre più le idee :fiorellino:

comunque sia grazie tante dell'aiuto!!

To Alcohol! The cause of - And solution to - All life' s problems

(Homer J. Simpson)

Link al commento
Condividi su altri siti

Archiviato

Questa discussione è archiviata e chiusa a future risposte.

×
×
  • Crea Nuovo...