15 Funzioni: passaggio di parametri per indirizzo e per valore, variabili globali e locali

Nell’articolo precedente abbiamo visto come si definisce e si dichiara una funzione, oggi andremo ad approfondire meglio la chiamata di funzione, in particolare ci occuperemo del passaggio dei parametri. Prima però, facciamo una breve ma necessaria introduzione sulle variabili che utilizziamo nei programmi.

Finora non abbiamo mai parlato dell’ambiente (o stato di esecuzione) dei programmi. Ebbene, tutte quelle variabili che abbiamo dichiarato dopo le librerie e prima del main, nei vari esempi che vi abbiamo proposto, appartengono all‘ambiente globale del programma. Pertanto le variabili dichiarate qui dentro, prendono il nome di variabili globali e sono sempre accessibili, modificabili e utilizzabili dal programma. Quando invece dichiariamo una funzione, la parte definita all’interno delle parentesi { }, è detta ambiente locale, e le variabili che dichiariamo al suo interno vengono dette variabili locali: esse non possono essere usate o modificare al di fuori di questo ambiente, e vengono “distrutte” subito dopo l’istruzione return della funzione. Vediamo un esempio:

 
#include <stdio.h>
//Parte dichiarativa globale
int x,y; //variabili globali
int fun(int a,int b) //funzione dichiarata in ambiente globale
{ //Ambiente locale
int i; //variabile locale
for (i=0; i<3; i++;)
{a=a+b; b=i;}
b=3;
return a; //Fine ambiente locale
}
void main()
{ //Ambiente locale (vale anche per il main)
x=1; y=2;  x=fun(x,y);
printf("%d", x);
//Fine ambiente locale 
}
//Fine del programma

Il programma assegna ad x e y rispettivamente il valore 1 e 2, dopodiché invoca la funzione fun passando i due valori ai parametri (a=x, b=y). La funzione fun assegna ad i il valore 0  poi passa ed eseguire il ciclo 3 volte: nel primo ciclo a=3 (2+1) e b=0 (i=0); nel secondo, a=3 (0+3) e b=1; nel terzo a=4 e b=2. Poi segue l’istruzione b=3, ma che non ha alcuna rilevanza perché il valore non viene ritornato (le modifiche che avvengono ai parametri a e b nel corso dell’esecuzione della funzione non modificano x e y). Nella return viene passato il parametro a=4, e la variabile i viene distrutta (pertanto sarebbe sbagliato scrivere un’ istuzione contenente i nel main, perché qui la nostra variabile locale non è visibile). Siccome x=fun(x,y) e il valore della return è a=4, allora x=4 (perché risulta fun(x,y)=4). Y da quando viene inizializzato, continua a valere 2 per tutto il programma.

OSSERVAZIONE: le funzioni possono essere tranquillamente dichiarate nel main o all’interno di altre funzioni (vedremo poi più avanti la ricorsività), in tal caso saranno però funzioni locali, e varranno le stesse proprietà delle variabili locali. Inoltre è lecito dare lo stesso nome a più variabili purché queste siano in AMBIENTI DIVERSI.

Nelle chiamate di funzione viste finora, abbiamo sempre utilizzato il passaggio di parametri per valore. Ovvero, al momento delle invocazioni delle funzioni viene copiato il valore del parametro attuale nella corrispondente cella del parametro formale (i primi sono i parametri/argomenti usati nella funzione nell’atto della chiamata, i secondi sono quelli dichiarati con tanto di tipo,nome e ordine nella definizione della funzione).

Oltre a questo, però, esiste anche un altro modo di passare i parametri: il passaggio di parametri per indirizzo. Questo consiste nel copiare, al posto del valore, l’indirizzo della cella contente il parametro attuale in un’opportuna cella del parametro formale. In C il passaggio dei parametri è sempre e solo per valore, ma è possibile simulare un passaggio per indirizzo nel seguente modo:

  • Utilizzando un puntatore per la definizione dei parametri formali;
  • Usando un operatore * o -> (di dereferenziazione) di puntatore;
  • Passando un indirizzo di variabile(&) come parametro attuale al momento della chiamata di funzione.

Vediammo un esempio:

#include<stdio.h>
int x,y;
int fun (int a, int *b)
{
int i=0;
for (i=0; i<3; i++)
{a=a+*b; *b=i;}
*b=3;
return a;
}
void main()
{
x=1; y=2;  x=fun(x,&y);
}

È molto simile all’esempio precedente. X e y vengono inizializzate a 1 e 2. Poi, viene invocata la funzione fun, nella quale la variabile y viene passata per indirizzo (x=a, &y=*b). Nella funzione viene inizializzata i, e viene eseguito lo stesso ciclo di prima sempre 3 volte. Dopodiché avviene l’assegnamento *b=3. ATTENZIONE: mentre nell’esempio di prima l’assegnamento b=3 non cambiava in alcun modo y perché utilizzavamo un passaggio di parametri per valore, il passaggio per indirizzo invece produce un assegnamento effettivo, quindi fa sì che il valore di y venga modificato(y=3). Infine viene ritornato il parametro a=4 dalla funzione fun e quindi x è uguale a 4.

Please follow and like us: