Copia del valore e copia dell'indirizzo

  1. differenza fra b=a e p=&a, in pratica
  2. b=a significa: copia il valore di a in b; non ci sono più relazioni fra a e b dopo la copia
  3. p=&a copia l'indirizzo: anche se è una copia, ora *p e a sono la stessa cosa
  4. cosa succede in memoria

Il seguente programma cambia.c fa capire la differenza fra assegnare il valore di una variabile (b=a) e assegnare il suo indirizzo (p=&a).

/*
  Effetti del cambiamento di una variabile.
*/

int main(void) {
  int a;
  int b;
  int *p;

  a=1;			/* a vale 1 */

  b=a;			/* il valore di a viene copiato in b */

  p=&a;			/* l'indirizzo di a viene messo in p */

  a=12;			/* a viene cambiato */

			/* quanto valgono b e *p a questo punto? */
  printf("*p vale %d\n", *p);
  printf("b vale %d\n", b);

  return 0;
}


Assegnare a b il valore di a significa semplicemente che il valore di a viene copiato nella zona di memoria di b. Da questo momento in poi, non esiste nessuna associazione fra a e b. In particolare, se si cambia il valore di a, questo non si riflette sul valore di b. È come fotocopiare un documento e poi fare delle modifiche solo sull'originale: chiaramente, la copia non viene modificata automaticamente.

Nel caso della assegnazione dell'indirizzo, quando si fa p=&a, da questo momento in poi, *p e a sono realmente la stessa zona di memoria. Quindi, da questo momento in poi, ogni modifica su a cambia anche *p e viceversa. Nell'esempio della documento fotocopiato, è come se usassimo due nomi diversi per indicare lo stesso documento: dato che il documento è sempre lo stesso, quando modifico uno dei due sto modificando anche l'altro. Questa associazione permane fino a che il valore di p non viene cambiato.

Attenzione! La seguente affermazione è sbagliata:

affermazione errata: dopo aver fatto a=12 il valore di *p viene aggiornato di conseguenza in modo automatico

Infatti, questa affermazione presuppone che a e *p siano due variabili memorizzate in due zone di memoria diverse, e che poi è il calcolatore che si preoccupa di far sí che i loro valori siano sincronizzati. Questo non è assolutamente vero: quando si memorizza 12 in a, questo valore non viene copiato in *p. Quello che invece succede è che *p ha la stessa zona di memoria di a e quindi il suo valore non può che essere lo stesso.

La figura qui accanto mostra lo stato della memoria subito dopo la assegnazione p=&a. In questo momento, i valori di a e b coincidono semplicemente perchè il valore di a è stato copiato in b e non è stato più modificato; invece, il valore di *p e di a coincidono perchè sono esattamente la stessa area di memoria.

Quando si fa la modifica a=12 del valore di a, la parte di memoria modificata è solo quella in cui è memorizzato a. La situazione diventa quindi come nella figura qui a fianco.

È chiaro che il valore di b non è stato alterato, visto che è memorizzato in una zona di memoria differente. D'altra parte, il valore di p è l'indirizzo di a, e quindi *p e a stanno nella stessa zona di memoria. Quindi, il valore di *p è quello memorizzato in questa zona, e quindi 12.

In conclusione, possiamo dire che la differenza fra assegnare il valore di una variabile come in b=a e assegnare il suo indirizzo come in p=&a è che, nel primo caso, una volta copiato il valore le due variabili vanno ognuna per la sua strada, nel secondo caso l'elemento puntato *p coincide con la variabile, e quindi cambia insieme alla variabile.