Linguaggio C - Classi di memoria

Prima di descrivere le classi di memoria, e' necessario introdurre alcune definizioni:

0 Tempo di vita di una entita' : Quanto di tempo in cui l'entita' (variabile o funzione) e' presente durante l'esecuzione del programma (Nozione dinamica).
0 Visibilita' di una entita' (scope) : Possibilita' di una entita' (variabile o funzione) di poter essere riferita all'interno del programma (Nozione statica).
In C esiste un principio: nessuna entita' e' riferibile non prima che sia stata o dichiarata o definita.

Il linguaggio C definisce una regola fondamentale sulla visibilita' delle entita': nel caso che due o piu' entita' differenti abbiano nomi uguali, l'entita' dichiarata nel blocco interno prevale su quella piu' esterna avente lo stesso nome.

Il linguaggio C prevede 4 classi di memoria da preporre alle variabili ed alle funzioni. Nessuna di esse e' obbligatoria, ed in loro assenza e' previsto un comportamento di default dipendente dal contesto.
Le classi di memoria sono:
o Auto
o Static
o Extern
o Register

Classe di memoria AUTO

La classe di memoria auto e' il default (e partanto puo' essere omessa) per le variabili locali, cioe' quelle variabili che sono definite entro un blocco o all'interno della definizione di una funzione.

Tali variabili, dette automatiche, vengono create all'entrata del blocco e non vengono inizializzate automaticamente, salvo che sia esplicitato diversamente dal programmatore. All'uscita del blocco vengono distrutte e perdono ogni valore assegnatogli. Non e' cosi' possibile che una variabile possa conservare un valore fra 2 esecuzioni dello stesso blocco o della stessa funzione. Pertanto:
o Il tempo di vita di una variabile automatica e' pari al tempo di vita del blocco in cui e' definita.
L'allocazione e la deallocazione della variabile automatica viene effettuata impiegando una struttura LIFO (Last In - First Out) come per es. lo STACK.
o La visibilita' (scope) di una variabile automatica e' limitata al blocco in cui e' definita.

N.B. - Non ha senso parlare di funzioni automatiche, poiche' una funzione non puo' essere locale ad un altro oggetto, ovvero non possono essere definite funzioni all'interno di blocchi. Inoltre una funzione ha un tempo di vita pari all'intera durata del programma.

N.B. - Ha senso parlare di variabili locali ad una funzione, poiche' la funzione viene definita da un blocco entro il quale possono venire definite a loro volta delle variabili automatiche.

Classe di memoria STATIC

La classe di memoria static non e' mai prevista di default, pertanto, se necessaria, deve essere esplicitata.

Una varibile static ha:
o Un tempo di vita pari all'intero programma.
L'allocazione e l'inizializzazione avviene una volta per tutte all'inizio del programma e le aree di memoria impiegate fanno parte dei dati globali del programma.
Per default le variabili statiche sono sempre inizializzate a zero.
Nel caso di inizializzazione esplicita, l'inizializzatore deve essere un'espressione costante.
o Una visibilita' (scope) limitata al blocco in cui e' definita se si tratta di una variabile locale; nel caso, invece, di una variabile esterna (nel senso, che e' definita all'esterno di ogni funzione), la visibilita' e' limitata al file in cui essa e' definita; in altri termini, l'utilizzo di una variabile static e' consentito solamente da parte delle funzioni definite nello stesso file sorgente.

Una funzione static ha:
o Un tempo di vita pari all'intero programma.
o Una visibilita' (scope) limitata al sorgente in cui e' definita; in altri termini, una funzione static puo' essere invocata solamente da altre funzioni che siano definite nello stesso file sorgente, oppure (ovviamente) da se' stessa (caso della ricorsione).

Classe di memoria EXTERN

La classe di memoria extern e' il default per le variabili esterne (scritte, cioe' all'esterno di ciascuna funzione) e per le funzioni.

Una variabile extern ha:
o Un tempo di vita pari all'intero programma.
L'allocazione e l'inizializzazione avviene una volta per tutte all'inizio del programma e le aree di memoria impiegate fanno parte dei dati globali del programma.
Per default le variabili extern sono sempre inizializzate a zero.
Nel caso di inizializzazione esplicita, l'inizializzatore deve essere un'espressione costante.
o Una visibilita' (scope) globale, cioe' una variabile esterna e' visibile da tutti i sorgenti che compongono il programma, a condizione che venga dichiarata almeno sui sorgenti dove se ne faccia uso.

Una funzione extern ha:
o Un tempo di vita pari all'intero programma.
o Una visibilita' (scope) globale, cioe' una funzione esterna e' visibile da tutti i sorgenti che compongono il programma, a condizione che venga dichiarata almeno sui sorgenti dove se ne faccia uso.

Per la definizione di una variabile o di una funzione esterna, il termine extern non deve essere impiegato.

Per dichiarare una variabile o una funzione definita all'esterno del sorgente attuale, occorre precedere la dichiarazione stessa con la parola chiave extern.
extern deve essere impiegata anche' nel caso, sebbene molto piu' raro, della dichiarazione di una variabile la cui definizione avvenga in un punto seguente del sorgente.

Vedi un esempio di sorgente

Classe di memoria REGISTER

La classe di memoria register definisce una varibile con caratteristiche della classe di memoria automatica, tranne il fatto di indicare al compilatore che la variabile venga inserita, se possibile, direttamente nei registri di memoria della CPU, piuttosto che allocarla sullo STACK. Poiche' l'accesso ai registri di CPU risulta essere molto piu' veloce dell'accesso in memoria, ne consegue che l'uso di variabili register puo' notevolmente migliorare le prestazioni di alcune funziolni critiche e con esse dell'intero programma.
E' quindi evidente, che la convenienza di definire variabili register aumenta con l'aumentare del numero di accessi che si prevede di effettuare su tali variabili. In quest'ottica risulta conveniente chiedere al compilatore di definire queste variabili nei registri macchina della CPU.

L'effettivo utilizzo dei registri di CPU per una variabile register dipende dalla implementazione del compilatore.
Le limitazioni tipiche sono in funzione della tipologia della variabile (es.: int, long, float, ...) e sul numero di registri di CPU disponibili per l'allocazione di variabili.
Come e' evidente, i limiti sono per lo piu' di natura hardware (riguardano direttamente l'architettura della CPU).

La classe register e' anche applicabile ai parametri formali di una funzione.
Esempio:

  int funzione1(int arg1, register int arg2, long arg3)
    { ... }
    

N.B. - Ad una variabile register non e' consentito di applicare l'operatore indirizzo &


Classi di memoria
auto static extern register
Variabili locali Si (default) Si Si (dichiarazione) Si
Variabili esterne No! Si Default (definizione)
Si (dichiarazione)
No!
Funzioni No! Si Default (definizione)
Si (dichiarazione)
No!

Nella tabella soprastante, si e' evidenziata la possibilita' di utilizzare esplicitamente le 4 classi di memoria in funzione delle entita'.
Con variabili locali si intendono le variabili dichiarate o definite all'interno di un blocco.
Con variabili esterne si sono indicate quelle variabili dichiarate o definite all'esterno di ciascuna funzione.

Per quanto riguarda la classe di memoria extern, e' stato indicato, oltre alla compatibilita' con le varie entita', che la sua presenza implica una dichiarazione, mentre la sua assenza nei casi di default implica una definizione.

Link ad ulteriori approffondimenti sui termini di dichiarazione e di definizione di entita'.


Indice-C Indice linguaggio C
At Home Umberto Zappi Home Page