Wie werden Variablennamen in C im Speicher gespeichert?

Lesezeit: 6 Minuten

Tylers Benutzeravatar
Tyler

Nehmen wir an, Sie haben in C eine Variable namens variable_name. Nehmen wir an, es befindet sich in 0xaaaaaaaaund an dieser Speicheradresse haben Sie die Ganzzahl 123. Mit anderen Worten, variable_name enthält 123.

Ich suche nach einer Klärung der Formulierung “variable_name liegt bei 0xaaaaaaaa“. Wie erkennt der Compiler, dass die Zeichenfolge “Variablenname” dieser bestimmten Speicheradresse zugeordnet ist? Ist die Zeichenfolge “Variablenname” irgendwo im Speicher gespeichert? Ersetzt der Compiler nur variable_name zum 0xaaaaaaaa wann immer es es sieht, und wenn ja, müsste es nicht den Speicher verwenden, um diese Ersetzung vorzunehmen?

  • Nicht ganz eine Antwort, aber dies könnte einige Lücken füllen: csee.umbc.edu/~chang/cs313.s02/stack.shtml

    – Douglas

    30. Januar 2013 um 19:47 Uhr


  • Nun, ohne Debug-Informationen wird der Variablenname nicht im Speicher gespeichert. Wenn Sie dies verstehen wollen, müssen Sie zuerst die Maschinensprache und die Assemblersprache verstehen.

    – Heiße Licks

    8. Februar 2013 um 2:02 Uhr

Benutzeravatar von Carl Norum
Karl Norum

Variablennamen existieren nicht mehr, nachdem der Compiler ausgeführt wurde (mit Ausnahme von Sonderfällen wie exportierten Globals in gemeinsam genutzten Bibliotheken oder Debug-Symbolen). Der gesamte Vorgang der Kompilierung soll diese symbolischen Namen und Algorithmen, die durch Ihren Quellcode dargestellt werden, in native Maschinenanweisungen umwandeln. Also ja, wenn Sie eine globale haben variable_nameund Compiler und Linker beschließen, es auf zu setzen 0xaaaaaaaadann wird überall dort, wo es im Code verwendet wird, nur über diese Adresse darauf zugegriffen.

Also um deine wörtlichen Fragen zu beantworten:

Wie erkennt der Compiler, dass die Zeichenfolge “Variablenname” dieser bestimmten Speicheradresse zugeordnet ist?

Die Toolchain (Compiler & Linker) arbeiten zusammen, um einen Speicherplatz für die Variable zuzuweisen. Es ist die Aufgabe des Compilers, alle Referenzen im Auge zu behalten, und der Linker fügt später die richtigen Adressen ein.

Ist die Zeichenfolge "variable_name" irgendwo im Gedächtnis gespeichert?

Nur während die Compiler läuft.

Ersetzt der Compiler nur variable_name zum 0xaaaaaaaa wann immer es es sieht, und wenn ja, müsste es nicht den Speicher verwenden, um diese Ersetzung vorzunehmen?

Ja, das ist ziemlich genau das, was passiert, außer dass es ein zweistufiger Job mit dem Linker ist. Und ja, es verbraucht Speicher, aber es ist der Compiler Speicher, nichts zur Laufzeit für Ihr Programm.

Ein Beispiel hilft vielleicht beim Verständnis. Probieren wir dieses Programm aus:

int x = 12;

int main(void)
{
    return x;
}

Ziemlich einfach, oder? OK. Nehmen wir dieses Programm, kompilieren es und sehen uns die Disassemblierung an:

$ cc -Wall -Werror -Wextra -O3    example.c   -o example
$ otool -tV example
example:
(__TEXT,__text) section
_main:
0000000100000f60    pushq   %rbp
0000000100000f61    movq    %rsp,%rbp
0000000100000f64    movl    0x00000096(%rip),%eax
0000000100000f6a    popq    %rbp
0000000100000f6b    ret

Siehst du das movl Linie? Es greift die globale Variable (in diesem Fall relativ zum Anweisungszeiger). Keine Erwähnung mehr von x.

Machen wir es jetzt etwas komplizierter und fügen eine lokale Variable hinzu:

int x = 12;

int main(void)
{  
    volatile int y = 4;
    return x + y;
}

Die Disassemblierung für dieses Programm ist:

(__TEXT,__text) section
_main:
0000000100000f60    pushq   %rbp
0000000100000f61    movq    %rsp,%rbp
0000000100000f64    movl    $0x00000004,0xfc(%rbp)
0000000100000f6b    movl    0x0000008f(%rip),%eax
0000000100000f71    addl    0xfc(%rbp),%eax
0000000100000f74    popq    %rbp
0000000100000f75    ret

Jetzt sind es zwei movl Anleitung und ein addl Anweisung. Das sieht man erstmal movl wird initialisiert y, von dem entschieden wird, dass es sich auf dem Stapel befindet (Basiszeiger – 4). Dann das nächste movl bekommt die globale x in ein Register eaxund die addl fügt hinzu y zu diesem Wert. Aber wie Sie sehen können, das wörtlich x und y Saiten gibt es nicht mehr. Sie waren Bequemlichkeiten für Sieder Programmierer, aber der Computer kümmert sich sicher nicht um sie zur Ausführungszeit.

  • Vielen Dank, das hat geholfen, die Dinge zu klären.

    – Tyler

    30. Januar 2013 um 20:16 Uhr

  • Tolle Erklärung dafür, wie C es macht. Beachten Sie, dass einige andere Sprachen (insbesondere moderne “dynamische” oder “Skriptsprachen”) möglicherweise symbolische Namen für Daten beibehalten und zur Laufzeit tatsächlich Speicher verwenden, um diese Zuordnungsinformationen zu speichern.

    – Russell Borogove

    30. Januar 2013 um 23:11 Uhr


  • Dies ist eine großartige Antwort. Nur eine Frage: Woher kennt der Compiler die Adresse, bevor er wirklich ausgeführt wird? Ich dachte, der Speicher wird dynamisch zugewiesen (daher könnten die Adressen in verschiedenen Läufen unterschiedlich sein).

    – Jackson-Geschichte

    28. Mai 2014 um 21:40 Uhr

  • @JacksonTale – das hängt stark davon ab, wie ein bestimmtes System konfiguriert ist, aber auf den meisten gängigen Systemen bedeutet virtueller Speicher, dass Ihr Prozess immer dieselbe logische Ansicht des Speichers hat, selbst wenn sich die zugrunde liegenden physischen Adressen von Lauf zu Lauf ändern. In den oben verwendeten Beispielen werden die Variablen relativ zum Befehlszeiger adressiert, ohnehin nicht durch eine absolute Adresse.

    – Karl Norum

    29. Mai 2014 um 5:39 Uhr


  • 0xfc ist die 8-Bit-Zweierkomplementdarstellung von -4.

    – Karl Norum

    23. Februar um 17:41 Uhr

Der AC-Compiler erstellt zunächst eine Symboltabelle, in der die Beziehung zwischen dem Variablennamen und seinem Speicherort gespeichert ist. Beim Kompilieren verwendet es diese Tabelle, um alle Instanzen der Variablen durch einen bestimmten Speicherort zu ersetzen, wie andere angegeben haben. Auf der Wikipedia-Seite findest du noch viel mehr dazu.

Alle Variablen werden vom Compiler ersetzt. Zuerst werden sie durch Referenzen ersetzt und später platziert der Linker Adressen anstelle von Referenzen.

Mit anderen Worten. Die Variablennamen sind nicht mehr verfügbar, sobald der Compiler durchlaufen ist

  • First references..then addresses ist das Wichtige, was Sie wissen müssen, wenn Sie mehrere Dateien kompilieren und später verknüpfen. +1 dafür.

    – PP

    30. Januar 2013 um 19:58 Uhr

Das nennt man ein Ausführungsdetails. Während das, was Sie beschreiben, bei allen Compilern, die ich je verwendet habe, der Fall ist, muss es nicht der Fall sein. Der AC-Compiler konnte jede Variable in eine Hashtabelle einfügen und sie zur Laufzeit nachschlagen (oder so ähnlich), und tatsächlich taten frühe JavaScript-Interpreter genau das (jetzt führen sie eine Just-In-TIme-Kompilierung durch, die zu etwas viel Roherem führt.)

Speziell für gängige Compiler wie VC++, GCC und LLVM: Der Compiler weist im Allgemeinen eine Variable einem Speicherort zu. Variablen mit globalem oder statischem Gültigkeitsbereich erhalten eine feste Adresse, die sich während der Ausführung des Programms nicht ändert, während Variablen innerhalb einer Funktion eine erhalten Stapel Adresse, dh eine Adresse relativ zum aktuellen Stapelzeiger, die sich jedes Mal ändert, wenn eine Funktion aufgerufen wird. (Dies ist eine zu starke Vereinfachung.) Stapeladressen werden ungültig, sobald die Funktion zurückkehrt, haben aber den Vorteil, dass sie praktisch keinen Overhead verwenden.

Sobald einer Variablen eine Adresse zugewiesen wurde, ist der Name der Variablen nicht mehr erforderlich, sodass er verworfen wird. Abhängig von der Art des Namens kann der Name zur Vorverarbeitungszeit (für Makronamen), zur Kompilierzeit (für statische und lokale Variablen/Funktionen) und zur Verbindungszeit (für globale Variablen/Funktionen) verworfen werden. Wenn ein Symbol exportiert wird ( für andere Programme sichtbar gemacht werden, damit sie darauf zugreifen können), wird der Name normalerweise irgendwo in einer “Symboltabelle” verbleiben, die tut beanspruchen eine triviale Menge an Arbeitsspeicher und Speicherplatz.

Ersetzt der Compiler einfach variable_name für 0xaaaaaaaa, wann immer er es sieht

Ja.

und wenn ja, müsste es nicht Speicher verwenden, um diese Ersetzung vorzunehmen?

Ja. Aber es ist der Compiler, nachdem er Ihren Code kompiliert hat, warum kümmern Sie sich um den Speicher?

1414590cookie-checkWie werden Variablennamen in C im Speicher gespeichert?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy