Variabili Globali in linguaggio C

Una variabile globale in linguaggio C è una variabile dichiarata all'esterno di qualsiasi funzione. Una variabile globale ha durata di vita statica e visibilità globale a livello di file.

Questa lezione spiega come dichiarare una variabile globale in linguaggio C e quali sono i suoi vantaggi e i suoi svantaggi.

Variabili globali

Abbiamo visto che per passare informazioni ad una funzione è possibile utilizzare i parametri.

Tuttavia, l'utilizzo dei parametri non è l'unico modo. Infatti, è possibile utilizzare anche delle Variabili Globali, in inglese Global Variables. Spesso queste variabili vengono chiamate anche variabili esterne, in inglese External Variables.

Per definizione, una variabile globale è una variabile dichiarata all'esterno di qualsiasi funzione. Una variabile globale ha le seguenti proprietà:

  • Durata di vita statica: la variabile globale esiste per tutta la durata dell'esecuzione del programma. In altre parole, la variabile globale esiste finché il programma è in esecuzione. In questo, una variabile globale è molto simile ad una variabile locale statica.
  • Visibilità globale a livello di file: una variabile globale è visibile in tutto il file in cui è dichiarata. In altre parole, una variabile globale è visibile in tutto il file in cui è dichiarata, comprese le funzioni dichiarate nel file stesso. Di conseguenza una variabile globale può essere acceduta e potenzialmente modificata da qualsiasi funzione del file.
Definizione

Variabili Globali

In linguaggio C una variabile globale è una variabile dichiarata all'esterno di qualsiasi funzione.

Una variabile globale esiste per tutta la durata di esecuzione di un programma e può essere acceduta e potenzialmente modificata da qualsiasi funzione del file in cui è dichiarata.

Un dettaglio molto importante riguarda la posizione delle variabili globali.

Abbiamo visto, in precedenza, che ad un processo in esecuzione corrispondente ad un programma C vengono allocate almeno quattro aree di memoria o segmenti.

Di questi segmenti ne abbiamo studiato lo scopo soltanto di uno, il segmento testo. Questo segmento contiene il codice macchina del programma.

Adesso possiamo comprendere lo scopo di un secondo segmento, il segmento dati. Questo segmento contiene le variabili globali e le variabili statiche che abbiamo visto nella lezione precedente.

Segmento di memoria Dati in cui sono memorizzate le variabili globali e quelle statiche
Figura 1: Segmento di memoria Dati in cui sono memorizzate le variabili globali e quelle statiche

Dichiarazione di una variabile globale

Per dichiarare una variabile globale, basta dichiararla all'esterno di qualsiasi funzione. Ad esempio, supponiamo di voler implementare una coppia di funzioni che realizzano un contatore che può crescere o decrescere. La prima funzione incrementa incrementa il contatore di 1, mentre la seconda funzione decrementa decrementa il contatore di 1. Il contatore è una variabile globale che viene dichiarata all'esterno di qualsiasi funzione:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>

/* Dichiarazione di una variabile globale */
int contatore = 0;

void incrementa() {
    /* Incrementa il contatore di 1 */
    contatore++;
}

void decrementa() {
    /* Decrementa il contatore di 1 */
    contatore--;
}

int main() {
    int prosegui = 1;

    while (prosegui) {
        int scelta;

        printf("Contatore: %d\n", contatore);
        printf("1. Incrementa\n");
        printf("2. Decrementa\n");
        printf("3. Esci\n");
        printf("Scelta: ");
        scanf("%d", &scelta);

        switch (scelta) {
            case 1:
                incrementa();
                break;
            case 2:
                decrementa();
                break;
            case 3:
                prosegui = 0;
                break;
            default:
                printf("Scelta non valida\n");
        }
    }

    return 0;
}

Il programma è molto semplice. Il contatore è una variabile globale che viene dichiarata all'esterno di qualsiasi funzione. Le funzioni incrementa e decrementa incrementano e decrementano il contatore di 1. La funzione main stampa il valore del contatore e chiede all'utente di scegliere se incrementare o decrementare il contatore. Se l'utente sceglie di uscire, il programma termina.

Provando a compilare e a eseguire il programma, possiamo ottenere un risultato molto simile al seguente:

Contatore: 0
1. Incrementa
2. Decrementa
3. Esci
Scelta: 1
Contatore: 1
1. Incrementa
2. Decrementa
3. Esci
Scelta: 1
Contatore: 2
1. Incrementa
2. Decrementa
3. Esci
Scelta: 2
Contatore: 1
1. Incrementa
2. Decrementa
3. Esci
Scelta: 2
Contatore: 0
1. Incrementa
2. Decrementa
3. Esci
Scelta: 3

Svantaggi delle variabili globali

Le variabili globali sono molto utili per la realizzazione di programmi. Tuttavia, come tutte le cose, anche le variabili globali hanno dei pro e dei contro.

Usare le variabili globali può risultare molto conveniente quando molte funzioni devono condividere dati oppure quando poche funzioni condividono grandi quantità di variabili. Tuttavia, in molti casi è meglio scambiare dati tra funzioni usando i parametri anziché condividere variabili. Le principali motivazioni sono:

  • Dal momento che una variabile globale è modificabile potenzialmente da un punto qualunque del nostro file sorgente, è molto difficile capire dove e quando una variabile globale viene modificata. Per cui, spesso effettuare il debug di un programma che utilizza variabili globali può risultare molto difficile. Inoltre, una funzione che modifica una variabile globale può avere effetti indesiderati su altre funzioni che utilizzano la stessa variabile globale.
  • Se modifichiamo il nome o il tipo di una variabile globale, ad esempio quando si manutiene un programma, dobbiamo poi ricordarci di modificare anche tutte le funzioni che utilizzano la variabile stessa. Questo può risultare molto complicato se il programma è molto grande.
  • Se ad una variabile globale viene assegnato un valore non corretto risulta difficile identificare la funzione o il punto di codice che ha causato il problema.
  • Funzioni che utilizzano variabili globali sono difficilmente riutilizzabili in altri programmi. In altre parole sono poco portabili.

In poche parole, l'utilizzo di variabili globali porta spesso a programmi più complessi e difficili da manutenere.

In Sintesi

In questa lezione abbiamo studiato le variabili globali. In particolare abbiamo visto che:

  • Una variabile globale è una variabile dichiarata all'esterno di qualsiasi funzione.
  • Una variabile globale ha le seguenti proprietà:
  • Durata di vita statica: la variabile globale esiste per tutta la durata dell'esecuzione del programma.
  • Visibilità globale a livello di file: una variabile globale è visibile in tutto il file in cui è dichiarata.
  • Le variabili globali sono molto utili per la realizzazione di programmi. Tuttavia, come tutte le cose, anche le variabili globali hanno dei pro e dei contro.

Nella prossima lezione studieremo il costrutto di blocco in linguaggio C.