Dipende dall'implementazione.
Ad esempio, un compilatore C potrebbe mantenere una tabella dei simboli durante la compilazione. Si tratta di una struttura di dati ricca che consente di eseguire push e popping degli ambiti, poiché ogni parentesi di apertura della dichiarazione composta {
introduce potenzialmente un nuovo ambito per nuove variabili locali. Oltre a gestire gli ambiti che vanno e vengono, registra le variabili dichiarate, e per ciascuna include i nomi e i loro tipi.
Questa struttura dati della tabella dei simboli supporta anche la ricerca delle informazioni di una variabile per nome, ad es. dal suo identificatore, e il compilatore lo fa quando lega le informazioni della variabile dichiarata agli identificatori grezzi che vede nel parse, quindi questo è abbastanza presto durante la compilazione.
Ad un certo punto, il compilatore assegna posizioni alle variabili. Forse le assegnazioni di posizione sono registrate nella stessa struttura dati della tabella dei simboli. Il compilatore potrebbe eseguire l'assegnazione della posizione direttamente durante l'analisi, ma è probabile che sia in grado di eseguire un lavoro migliore se attende non solo dopo l'analisi, ma dopo l'ottimizzazione generale.
Ad un certo punto, per le variabili locali, il compilatore assegna una posizione di stack o un registro CPU (può essere più complesso in quanto la variabile può effettivamente avere più posizioni, come una posizione di stack per alcune parti del codice generato e un registro CPU per altre sezioni).
Infine, il compilatore genera codice effettivo: istruzioni macchina che fanno riferimento ai valori delle variabili direttamente dai loro registri CPU o posizione di stack assegnata, come necessario per eseguire il codice che viene compilato. Ogni riga di codice sorgente viene compilata con le proprie serie di istruzioni di codice macchina, pertanto le istruzioni generate codificano non solo le operazioni (aggiunta, sottrazione) ma anche le posizioni delle variabili a cui si fa riferimento.
Il codice oggetto finale che esce dal compilatore non ha più nomi e tipi di variabili; ci sono solo posizioni, posizioni dello stack o registri della CPU. Inoltre non esiste una tabella di posizioni, ma piuttosto queste posizioni vengono utilizzate da ciascuna istruzione macchina conoscendo la posizione in cui è memorizzato il valore della variabile. Nessuna ricerca di identificatori nel codice di runtime, ogni bit di codice generato conosce semplicemente l'operazione da eseguire e la / le posizione / i da utilizzare.
Quando il debugging è abilitato durante la compilazione, il compilatore emetterà un modulo della tabella dei simboli in modo che, ad esempio, i debugger conoscano i nomi delle variabili nelle varie posizioni dello stack.
Alcuni altri linguaggi hanno la necessità di cercare gli identificatori dinamicamente in fase di runtime, quindi possono anche fornire qualche forma di tabella dei simboli a supporto di tali esigenze.
Gli interpreti hanno una vasta gamma di opzioni. Potrebbero mantenere una struttura di dati simile a una tabella di simboli da utilizzare durante l'esecuzione (oltre all'uso durante l'analisi), sebbene invece di assegnare / tracciare una posizione di stack, è sufficiente memorizzare il valore per la variabile, associato alla voce della variabile nella tabella dei simboli struttura dati.
Una tabella dei simboli è forse memorizzata nell'heap piuttosto che nello stack (sebbene l'utilizzo dello stack per scope e variabili sia certamente possibile, e inoltre può simulare uno stack nell'heap per ottenere il vantaggio della cache di compattare la variabile valori vicini l'uno all'altro), quindi un interprete sta probabilmente usando la memoria heap per memorizzare i valori della variabile mentre un compilatore usa le posizioni dello stack. In generale, anche l'interprete non ha la libertà di utilizzare i registri della CPU come memoria per i valori della variabile poiché i registri della CPU sono altrimenti occupati a eseguire le righe di codice dell'interprete stesso ...