Passaggio di parametro per riferimento in C

Passaggio di parametro per riferimento in C

Misconception terza puntata

Si dice spesso che in linguaggio C il passaggio di parametro delle funzioni possa avvenire in due modi:

  • per valore
  • per riferimento
  • In questo post vogliamo spiegare la differenza tra passaggio per valore e “per riferimento”, mostrando che in realtà, in linguaggio C, non esiste il passaggio di parametro per riferimento, ovvero esiste solo il passaggio di parametro per valore.

    Per capire di cosa stiamo parlando facciamo un esempio e diamo delle definizioni.

    Passaggio di parametri per valore

    Passare i parametri per valore vuol dire che la funzione chiamata si fa una copia locale di ogni variabile passata. La funzione alloca cioè spazio per ogni suo variabile passata, spazio che verrà liberato all’uscita della funzione (cioè dopo il return).

    Di conseguenza, se la variabile cambia valore dentro la funzione, questo verrà perso (all’uscita). Inoltre, la copia originale presente nella funzione chiamante (ad esempio il main) rimane invariata.

    Facciamo un esempio per capire:

int main()
{
   int a;
   a=3;
   f(a);
   //qui a vale sempre 3
}
void f(int a)
{
   a = a + 4;
   return;
}

Qui la variabile a nel main vale 3 prima della chiamata a funzione e rimane tale anche dopo. Questo nonostante la funzione f modifichi il valore di a al suo interno. Nella chiamata a funzione presente nel main alla riga 5 l’esecutore passa alla funzione (riga 8) e sostituisce al parametro formale a il numero 3 ( parametro attuale ). La funzione aveva precedentemente allocato lo spazio necessario per a (da non confondere con lo spazio che era stato allocato per la variabile a del main. Quindi in generale:

Nel passaggio per valore la funzione chiamata fa una copia locale del parametro e quindi modifica la copia locale lasciando intatta quella del main. Lo spazio in memoria allocato per la copia locale viene liberato all’uscita della funzione.

Definizione chiave passaggio di parametro per valore

Passaggio di parametro per riferimento (?)

int main()
{
   int a;
   a=3;
   f(&a);
   //qui a vale 7
}
void f(int *a)
{
   /***********************************************
     qui a non vale 3 perchè a è di tipo puntatore 
     a intero, cioè una variabile che può contenere 
     l'indirizzo di un'altra variabile; 
     in questo caso l'indirizzo di a (del main)
    **********************************************/
   *a = *a + 4;   
   return;
}

Qui la funzione chiamata (f) non fa una copia locale della variabile a ma lavora direttamente con quella presente nel main.

Rispetto a prima la differenza tra nel fatto che il parametro a è una variabile di tipo: int * e cioè un puntatore a intero. A questa varibile viene passato l’indirizzo della variabile a (cioè: &a).

Quindi la variabile a nel main (che è di tipo intero) risulterà modificata; la funzione infatti modifica l’elemento puntato da a (cioè: *a) che nella funzione è un puntatore a intero.
Per capire ancora megio basti guardare cosa succede in RAM nei due casi come mostrato in figura:

Passaggio di parametri per valore e per riferimento in RAM

Perché non esiste il passaggio per riferimento

Il passaggio di parametro per riferimento non esiste perché la funzione fa una copia locale dell’indirizzo, copia che verrà liberata all’uscita della funzione. Cioè si ha un passaggio per valore dell’indirizzo (che è sempre un valore).

Al massimo quindi si può dire che esiste il passaggio di parametro del riferimento (e cioè del puntatore).
Quindi:

Una funzione fa sempre copie locali di ogni suo parametro.

É probabile che l’errata convinzione derivi da altri linguaggi di programmazione come Pascal o Visual Basic; qui infatti il passaggio per valore o “tramite” puntatore si fa usando parole chiave specifiche. In Pascal ad esempio si usa la parola chiave var per indicare il passaggio per riferimento,; in Visual Basic si usano le parole chiave ByVal e ByRef prima di ogni parametro.

Conclusioni

Possiamo quindi affermare a ragion veduta che: dire che in C si possa fare il passaggio di parametro per riferimento è una Misconception.

Siete d’accordo? Cosa ne pensate? Ditelo nei commenti a questo post.

PS: a questo link trovate un interessante approfondimento sulla differenza tra passaggio per valore o per riferimento in Java.