Das hängt von der Implementierung ab.
Beispielsweise kann ein C-Compiler während der Kompilierung eine Symboltabelle verwalten. Dies ist eine umfangreiche Datenstruktur, die das Verschieben und Löschen von Bereichen ermöglicht, da jede Klammer zum Öffnen von zusammengesetzten Anweisungen {
möglicherweise einen neuen Bereich für neue lokale Variablen einführt. Zusätzlich zur Behandlung der kommenden und gehenden Bereiche werden die deklarierten Variablen aufgezeichnet und für jeden die Namen und ihre Typen enthalten.
Diese Symboltabellendatenstruktur unterstützt auch das Nachschlagen der Informationen einer Variablen nach Namen, z. B. nach ihrem Bezeichner, und der Compiler tut dies, wenn er die deklarierten Variableninformationen an Rohbezeichner bindet, die er in der Analyse sieht. Dies ist also ziemlich früh während der Kompilierung.
Irgendwann weist der Compiler den Variablen Positionen zu. Möglicherweise werden Standortzuweisungen in derselben Symboltabellendatenstruktur aufgezeichnet. Der Compiler kann die Standortzuweisung direkt während des Parsens durchführen, kann jedoch wahrscheinlich bessere Arbeit leisten, wenn er nicht nur nach dem Parsen, sondern auch nach der allgemeinen Optimierung wartet.
Zu einem bestimmten Zeitpunkt weist der Compiler für lokale Variablen entweder einen Stapelspeicherort oder ein CPU-Register zu (dies kann komplexer sein, da die Variable tatsächlich mehrere Speicherorte haben kann, z. B. einen Stapelspeicherort für einige Teile des generierten Codes und eine CPU für andere Abschnitte registrieren).
Schließlich generiert der Compiler den tatsächlichen Code: Maschinenanweisungen, die die Werte der Variablen direkt anhand ihrer CPU-Register oder der zugewiesenen Stapelposition referenzieren, je nach Bedarf, um den zu kompilierenden Code auszuführen. Jede Zeile des Quellcodes wird zu einer eigenen Reihe von Maschinencode-Anweisungen kompiliert, sodass die generierten Anweisungen nicht nur die Operationen (Addieren, Subtrahieren), sondern auch die Positionen der Variablen codieren, auf die verwiesen wird.
Der endgültige Objektcode, der aus dem Compiler kommt, hat keine Variablennamen und -typen mehr. Es gibt nur Speicherorte, Stapelspeicherorte oder CPU-Register. Ferner gibt es keine Tabelle von Orten, sondern diese Orte werden von jedem Maschinenbefehl verwendet, der den Ort kennt, an dem der Wert der Variablen gespeichert ist. Kein Nachschlagen von Bezeichnern im Laufzeitcode, jedes Bit des generierten Codes kennt einfach die auszuführende Operation und die zu verwendenden Speicherorte.
Wenn das Debuggen während der Kompilierung aktiviert ist, gibt der Compiler eine Form der Symboltabelle aus, sodass Debugger beispielsweise die Namen der Variablen an den verschiedenen Stapelpositionen kennen.
Einige andere Sprachen müssen zur Laufzeit dynamisch nach Bezeichnern suchen, sodass sie möglicherweise auch eine Art Symboltabelle zur Unterstützung dieser Anforderungen bereitstellen.
Dolmetscher haben eine Vielzahl von Optionen. Sie behalten möglicherweise eine symboltabellenähnliche Datenstruktur zur Verwendung während der Ausführung bei (zusätzlich zur Verwendung während des Parsens). Anstatt jedoch einen Stapelspeicherort zuzuweisen / zu verfolgen, speichern Sie einfach den Wert für die Variable, der dem Eintrag der Variablen in der Symboltabelle zugeordnet ist Datenstruktur.
Eine Symboltabelle wird möglicherweise eher im Heap als auf dem Stapel gespeichert (obwohl die Verwendung des Stapels für Bereiche und Variablen durchaus möglich ist, und außerdem kann sie einen Stapel im Heap imitieren, um den cachefreundlichen Vorteil des Packens der Werte der Variablen in der Nähe jedes Stapels zu erzielen other), daher verwendet ein Interpreter wahrscheinlich Heapspeicher zum Speichern der Variablenwerte, während ein Compiler Stapelpositionen verwendet. Im Allgemeinen hat der Interpreter auch nicht die Freiheit, CPU-Register als Speicher für Variablenwerte zu verwenden, da die CPU-Register ansonsten damit beschäftigt sind, die Codezeilen des Interpreters selbst auszuführen ...