In questa lezione vengone descritte le possibili classi di memorizzazione di una variabile in C/C++.
L’appartenenza ad una classe di memorizzazione determina il ciclo di vita di una variabile ed in particolare, quindi, l’intervallo di tempo in cui è definita e può essere utilizzata. La classe di memorizzazione di una variabile, come vedremo, è determinata dal programmatore a seconda del punto del programma in cui viene definita. Prima di introdurre le classi di memorizzazione vengono proposti alcuni richiami legati ai concetti di visibilità e validità di una variabile.
Nei linguaggi a blocchi innestati lo scope di una variabile è quello del blocco in cui è dichiarata ed i suoi blocchi interni.
La visibilità di una variabile può essere oscurata da una variabile con lo stesso nome definita in un blocco più interno come nell’esempio seguente.
Il tempo di binding (legame) è il momento in cui ad un oggetto viene effettivamente associata una specifica proprietà/attributo, ad esempio il momento in cui ad una variabile viene assegnato lo spazio di memoria, il nome, o il tipo.
Si distingue in genere tra:
Early binding è generalmente riferito al tempo di compilazione.
Late binding è generalmente riferito al tempo di esecuzione, o in generale ad un momento “successivo”: ad esempio array allocati dinamicamente, legame ritardato del tipo dei parametri effettivi.
Il legame variabile-tipo avviene in genere a tempo di compilazione affinchè sia possibile la generazione delle istruzioni in linguaggio macchina.
Variabile con validità “locale”: la sua validità è circoscritta all’ambiente in cui è definita.
Variabile con validità “globale”: è comune a più ambienti.
Ciclo di vita delle variabili
Regola l’intervallo di tempo nel corso del quale essa risulta allocata ed è pertanto valida la corrispondenza:
nome-locazione di memoria-valore.
Per le variabili in C/C++, la definizione specifica la classe di memorizzazione, cioè:
Classi di memorizzazione del C/C++ (storage classes):
Un processo è un programma in esecuzione. Ad ogni programma viene assegnata un’area di memoria atta a contenere istruzioni e dati. In figura è mostrato lo schema di allocazione di un programma diviso in quattro aree:
Lo schema di allocazione deve essere condiviso dal compilatore, dal collegatore e dal caricatore. I sotto-programmi possono avere un’area codice separata dall’area codice del programma principale, ma i dati e le informazioni necessarie alla loro attivazione sono memorizzate in una struttura chiamata record di attivazione e memorizzata nell’area stack di cui sopra. Pertanto i sotto-programmi “vivono” utilizzando l’area dati del programma dati del programma principale, i record di attivazione sono allocati nello stack secondo la politica LIFO (Last In First Out).
Sono le variabili locali ad un blocco di istruzioni.
Sono definite in un blocco di istruzioni e sono allocate e deallocate con esso.
La visibilità lessicale è locale al blocco.
Nell’immagine in memoria del processo (cioè del programma in esecuzione), sono allocate nell’area stack. Esse infatti per essere definite all’interno di un blocco sono sicuramente all’interno di un record di attivazione di un sotto-programma.
Sono le variabili globali e vengono definite all’esterno di ogni blocco.
La visibilità lessicale si estende a tutto il programma, ma per renderle visibili anche da procedure contenute in file diversi, devono essere ivi dichiarate con la parola chiave extern.
La loro estensione temporale si estende a tutto il programma (sono allocate all’inizio del programma per essere poi deallocate alla fine dello stesso).
In memoria vengono allocate nell’area dati statici o globale.
Sono variabili automatiche prefissate con la parola chiave static.
La visibilità lessicale è locale al blocco in cui sono definite.
La loro estensione temporale si estende a tutto il programma (sono allocate all’inizio del programma per essere poi deallocate alla fine dello stesso).
In memoria vengono allocate nell’area dati globale.
Sono variabili esterne prefissate con la parola chiave static.
La visibilità lessicale è locale al file in cui sono definite.
La loro estensione temporale si estende a tutto il programma (sono allocate all’inizio del programma per essere poi deallocate alla fine dello stesso).
In memoria vengono allocate nell’area dati globale.
Sono variabili automatiche prefissate con la parola chiave register.
La visibilità lessicale è locale al blocco in cui sono definite.
Sono allocate e deallocate con il blocco di istruzioni in cui sono contenute.
Se possibile vengono allocate in un registro del processore, altrimenti nell’area stack.
Può convenire dichiarare register una variabile automatica usata di frequente, in modo che l’allocazione in un registro di macchina ne aumenti la velocità di accesso.
Sono definite durante l’esecuzione del programma e sono accessibili mediante puntatori.
L’allocazione e la deallocazione sono controllate dal programmatore.
In memoria vengono allocate nell’area heap.
Nell’esempio una variabile intera è allocata dinamicamente mediante l’operatore new. L’istruzione:
a= new int
;
alloca spazio per un intero attraverso la chiamata all’operatore new il quale restituisce l’indirizzo dell’area di memoria allocata. Tale indirizzo può essere quindi assegnato al puntatore “a” che è un puntatore a tipo intero. In seguito nell’esempio l’area di memoria allocata viene inizializzata attraverso il puntatore. L’operatore di de-referenziazione è utilizzato a tale scopo. Il dato ora contenuto nell’area di memoria allocata viene quindi passato alla funzione “accumula” già introdotta nell’esempio 1.
Mostra codice1. Strutture e typedef. Record in C/C++: Concetti Base
4. Puntatori a tipi di dato strutturati. Allocazione Dinamica
5. Puntatori: aspetti avanzati
7. Asserzioni
8. Gestione delle eccezioni. Concetti base
9. Programmazione modulare: concetti base
10. Programmazione Modulare: Meccanismi e Strumenti a supporto in C/C++
12. Esercitazione: Strutture Dati Pila e Coda
13. Esercitazione. Strutture Dati: Lista Concatenata
14. Meccanismi di Incapsulamento in C++ Namespaces
15. Programmazione orientata agli oggetti. Introduzione
B. Fadini, C. Savy: Fondamenti di Informatica I, Liguori Editore
Parte II, Cap. 13, par. 3,4,5,6,7,8,9