GeeksforGeeks (Deutsch)

C ist eine Mid-Level-Sprache und benötigt einen Compiler, um sie in einen ausführbaren Code umzuwandeln, damit das Programm auf unserem Rechner ausgeführt werden kann.

Wie kompilieren wir ein C-Programm und führen es aus?
Nachfolgend sind die Schritte aufgeführt, die wir auf einem Ubuntu-Rechner mit gcc-Compiler verwenden.

Kompilierung

  • Wir erstellen zunächst ein C-Programm mit einem Editor und speichern die Datei als Dateiname.c
 $ vi filename.c
  • Das Diagramm rechts zeigt ein einfaches Programm zum Addieren zweier Zahlen.

compil31

  • Dann kompilieren Sie es mit dem folgenden Befehl.
 $ gcc –Wall filename.c –o filename
  • Die Option -Wall aktiviert alle Warnmeldungen des Compilers. Diese Option wird empfohlen, um besseren Code zu erzeugen.
    Die Option -o wird verwendet, um den Namen der Ausgabedatei anzugeben. Wenn wir diese Option nicht verwenden, wird eine Ausgabedatei mit dem Namen a.out erzeugt.

compil21

  • Nach der Kompilierung wird eine ausführbare Datei erzeugt, die wir mit dem folgenden Befehl ausführen.
 $ ./filename 

Wie läuft der Kompilierungsprozess ab?
Compiler wandelt ein C-Programm in eine ausführbare Datei um. Es gibt vier Phasen, damit aus einem C-Programm eine ausführbare Datei wird:

  1. Vorverarbeitung
  2. Kompilierung
  3. Assemblierung
  4. Verknüpfung

Durch die Ausführung des folgenden Befehls erhalten wir alle Zwischendateien im aktuellen Verzeichnis zusammen mit der ausführbaren Datei.

 $gcc –Wall –save-temps filename.c –o filename 

Der folgende Screenshot zeigt alle erzeugten Zwischendateien.

compil4

Lassen Sie uns der Reihe nach sehen, was diese Zwischendateien enthalten.

Vorverarbeitung

Dies ist die erste Phase, die der Quellcode durchläuft. Diese Phase umfasst:

  • Entfernen von Kommentaren
  • Erweiterung von Makros
  • Erweiterung der eingeschlossenen Dateien.
  • Bedingte Kompilierung

Die vorverarbeitete Ausgabe wird im Dateinamen gespeichert.i. Schauen wir uns an, was in filename.i steht: mit $vi filename.i
In der obigen Ausgabe ist die Quelldatei mit vielen, vielen Infos gefüllt, aber am Ende bleibt unser Code erhalten.
Auswertung:

  • printf enthält jetzt a + b statt add(a, b), das liegt daran, dass die Makros erweitert wurden.
  • Kommentare werden entfernt.
  • #include<stdio.h> fehlt, stattdessen sehen wir viel Code. Die Header-Dateien wurden also erweitert und in unsere Quelldatei aufgenommen.

Kompilieren

Der nächste Schritt ist das Kompilieren von Dateiname.i und das Erzeugen einer zwischenkompilierten Ausgabedatei Dateiname.s. Diese Datei besteht aus Anweisungen auf Assembler-Ebene. Schauen wir uns diese Datei mit $vi filename.s an

Bild

Der Schnappschuss zeigt, dass sie in Assembler-Sprache ist, die Assembler verstehen kann.

Assemblierung
In dieser Phase wird die Datei filename.s als Eingabe genommen und von Assembler in filename.o umgewandelt. Diese Datei enthält Anweisungen auf Maschinenebene. In dieser Phase wird nur der vorhandene Code in Maschinensprache umgewandelt, die Funktionsaufrufe wie printf() werden nicht aufgelöst. Betrachten wir diese Datei mit $vi filename.o

compil7

Verknüpfung

Dies ist die letzte Phase, in der die Verknüpfung aller Funktionsaufrufe mit ihren Definitionen erfolgt. Linker weiß, wo all diese Funktionen implementiert sind. Linker macht auch einige zusätzliche Arbeit, er fügt unserem Programm zusätzlichen Code hinzu, der benötigt wird, wenn das Programm startet und endet. Zum Beispiel gibt es einen Code, der zum Einrichten der Umgebung benötigt wird, wie die Übergabe von Kommandozeilenargumenten. Diese Aufgabe kann leicht mit $size filename.o und $size filename überprüft werden. Durch diese Befehle wissen wir, wie die Ausgabedatei von einer Objektdatei zu einer ausführbaren Datei anwächst. Das liegt an dem zusätzlichen Code, den der Linker zu unserem Programm hinzufügt.

compil8

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.