PROGRAMMIAMO
C++ - Variabili globali
Variabili globali

In C++ una variabile si dice globale quando è dichiarata all'esterno di ogni blocco di programma, cioè fuori dal main e fuori dalle funzioni. Si consideri il seguente esempio:

#include <cstdlib>
#include <iostream>

using namespace std;

int pop(void);

unsigned int num; //variabile globale

int main(int argc, char *argv[])
{
int c; // variabile locale al main

cout<<"Inserisci un numero intero e positivo: ";
cin>>num;

while (num>0)
{
c = pop();
cout<<"Ho estratto la cifra: "<<c<<"\n";
}

system("PAUSE");
return EXIT_SUCCESS;
}

int pop(void)
{
int cifra; // variabile locale alla funzione

cifra = num%10;
num = num/10;

return cifra;
}

La variabile num, dichiarata fuori e prima del main, è una variabile globale. Ciò significa che essa è visibile in tutto il file e quindi può essere usata sia dal main che dalla funzione pop.

Il funzionamento del programma è abbastanza semplice: pop estrae una cifra alla volta da num e torna la cifra estratta al main che la visualizza. L'operazione di estrazione della cifra implica che la funzione pop possa effettivamente togliere la cifra da num, cioè modificare il valore di num. Questo avviene con l'istruzione:

num = num/10;

Tale operazione è possibile in quanto num è una variabile globale e dunque la funzione può modificarla liberamente.

Visibilità e durata

Per quanto riguarda la visibilità, come si è detto le variabili globali sono visibili in tutto il file nel quale sono dichiarate dal punto in cui sono dichiarate fino alla fine del file stesso. Questo significa che una variabile globale non può essere utilizzata prima della sua dichiarazione, come in questo esempio:

#include <cstdlib>
#include <iostream>

using namespace std;

int pop(void);

int main(int argc, char *argv[])
{
int c; // variabile locali al main

cout<<"Inserisci un numero intero e positivo: ";
cin>>num; // qui la variabile num non può essere usata (errore!)

while (num>0)
{
c = pop();
cout<<"Ho estratto la cifra: "<<c<<"\n";
}

system("PAUSE");
return EXIT_SUCCESS;
}

unsigned int num; //variabile globale dichiarata fra le due funzioni

int pop(void)
{
int cifra; // variabile locale alla funzione

cifra = num%10;// qui la variabile num può essere usata
num = num/10;

return cifra;
}

Di solito le variabili globali vengono sempre dichiarate all'inizio del file in cui sono usate, perciò il problema dell'esempio precedente si presenta assai di rado.

Un altro problema invece sorge quando si vuole usare una variabile globale fuori dal file in cui è stata dichiarata (per esempio quando una variabile globale è dichiarata nel file che contiene le funzioni e si vuole usarla nel file che contiene il main). In questi casi all'inizio del file che non contiene la dichiarazione bisogna scrivere (per esempio):

extern double numero;

dove la parola chiave extern indica appunto che la variabile numero è esterna, cioè globale ma dichiarata altrove.

La durata delle variabili globali è estesa all'intera durata del programma: esse conservano il proprio valore fino alla fine dell'esecuzione del programma.

Variabili globali e variabili locali con lo stesso nome

Se una variabile locale (per esempio interna a una funzione) ha lo stesso nome di un'altra variabile globale, la variabile locale nasconde sempre la variabile globale. Questo significa che dentro alla funzione verrà sempre usata la variabile locale. Per esempio:

#include <cstdlib>
#include <iostream>

using namespace std;

int funz(void);

int val=5; //variabile globale

int main(int argc, char *argv[])
{

cout<<funz()<<"\n";

system("PAUSE");
return EXIT_SUCCESS;
}

int funz(void)
{
int val; // variabile locale alla funzione con lo stesso nome della variabile globale

val = 10;

return val;
}

Nell'esempio precedente lo stesso nome val corrisponde a due variabili: una variabile globale e una variabile locale alla funzione funz. Pertanto la variabile locale alla funzione nasconde (dentro la funzione) la corrispondente variabile globale (il programma visualizza il valore 10).

Se in un caso del genere si volesse, all'interno della funzione, usare la variabile globale, bisognerebbe ricorrere a un operatore detto scope resolution, che si indica con i due punti e si usa così:

#include <cstdlib>
#include <iostream>

using namespace std;

int funz(void);

int val=5; //variabile globale

int main(int argc, char *argv[])
{

cout<<funz()<<"\n";

system("PAUSE");
return EXIT_SUCCESS;
}

int funz(void)
{
int val; // variabile locale alla funzione con lo stesso nome della variabile globale

val = 10;

return ::val;//in questo caso la funzione usa la variabile globale
}

I due punti davanti a val nell'esempio precedente fanno sì che la funzione usi la variabile globale: il programma visualizza dunque il valore 5.

 

A cosa servono le variabili globali

Si potrebbe credere che le variabili globali risolvano tutta una serie di problemi: per il fatto di essere visibili e utilizzabili da tutti, con le variabili globali si potrebbe fare a meno di passare i parametri alle funzioni e di usare il valore di ritorno. Inoltre le funzioni potrebbero automaticamente modificare i valori delle variabili globali, senza aver bisogno di usare il meccanismo del passaggio di parametri per riferimento.

In realtà le variabili globali creano molti più problemi di quanti ne risolvono, ragion per cui il loro uso è in generale fortemente sconsigliato. Anzitutto rendono il programma molto più difficile da leggere e da correggere in caso di errori: infatti se una variabile può essere usata e modificata da tutti, il suo valore può essere cambiato in qualsiasi punto del programma (e addirittura all'interno di un differente file).

Inoltre risulta molto più complicato e difficile gestire i nomi delle variabili: si rischia continuamente di ridefinire per errore una variabile già dichiarata altrove come globale o di usare (magari per qualche banale errore di battitura scrivendo i nomi delle variabili) una variabile globale definita da qualche altra parte per scopi completamente diversi.

Infine le funzioni diventano in realtà molto più complesse da scrivere e da usare se si utilizzano le variabili globali per passare i valori da e verso la funzione: infatti chi scrive la funzione è obbligato in questo modo a sapere quali sono i nomi delle variabili globali usate dal main per il trasferimento dei valori e viceversa.

Detto tutto ciò, vi sono alcuni casi, in verità molto rari, in cui le variabili globali sono comode (anche se non sono quasi mai indispensabili). Per esempio se una funzione usa un valore che viene acquisito una volta sola dal main e non cambia mai fra una chiamata e l'altra alla funzione, potrebbe essere preferibile evitare di passare ogni volta quel valore alla funzione: in questo caso l'uso di una variabile globale velocizza il programma (abbreviando i tempi di chiamata alla funzione) e lo rende persino più semplice da leggere.

Un altro caso in cui potrebbe essere utile una variabile globale è quando si vuole che la funzione abbia accesso e possa modificare la stessa variabile usata nel main. E' vero che questo problema può essere risolto usando il passaggio di parametri per argomento, ma ci sono situazioni in cui l'uso di una variabile globale risulta più semplice.

Infine se si ha bisogno di una funzione che restituisca al chiamante più di un risultato (cosa impossibile da fare con l'istruzione return), potrebbe essere comodo ricorrere alle variabili globali.

 

link precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it