La visibilità (scope) e la durata (lifetime) delle variabili sono alcuni degli aspetti chiave della struttura di un programma in C. La visibilità è la parte del codice in cui una variabile è accessibile per nome. La durata determina quando una variabile esiste realmente in memoria.
Storia della questione
Il C è stato progettato per il controllo a basso livello, quindi offre un approccio flessibile ma pericoloso alla visibilità e alle durate tramite la classificazione delle variabili in base al luogo di dichiarazione (locale, file, globale, statica).
Problema
Una comprensione errata di scope/lifetime porta a bug classici: tentativi di accesso a variabili non accessibili o già distrutte (use-after-free), conflitti di nome tra variabili globali e locali (shadowing), modifica non intenzionale di variabili globali.
Soluzione
Definire esplicitamente il tipo di storage necessario (auto, static, extern), utilizzare saggiamente la visibilità locale, minimizzare il numero di variabili globali e distinguere chiaramente tra lifetime nello stack e fuori dallo stack.
Esempio di codice:
int global_var; // Globale, vive per tutto il runtime void func() { int local_var = 5; // Automatica, vive all'interno di func() static int stat_var = 0; // Statica, vive tra le chiamate stat_var++; }
Caratteristiche chiave:
Cosa succede se dichiari due variabili con lo stesso nome in blocchi diversi?
La variabile interna nasconderà quella esterna (variabile shadow). Questo può portare a errori imprevisti.
int x = 10; ... if (1) { int x = 50; printf("%d", x); // stampa 50, x globale è nascosto }
Qual è la durata di una variabile automatica definita all'interno di una funzione?
Esiste solo durante la chiamata della funzione. Dopo l'uscita, la memoria viene liberata e il valore persa.
Può una variabile locale statica essere utilizzata al di fuori della funzione in cui è dichiarata?
No, la sua visibilità è solo all'interno della funzione. È invisibile dall'esterno, anche se la durata è per tutto il tempo di esecuzione del programma.
void f() { static int x = 0; } // Non accessibile al di fuori di f()
static vs auto).Un programmatore alle prime armi crea un contatore all'interno di un ciclo come statico, e questo contatore " accumula" valori tra le iterazioni, anche se ci si aspettava che si azzerasse ogni volta.
Pro:
Contro:
Un programmatore usa statico esclusivamente per il caching, mentre per esigenze temporanee utilizza normali variabili auto.
Pro:
Contro: