Ein Compiler ist ein Computerprogramm, das Code aus einer Programmiersprache (der Quellsprache) in eine andere Programmiersprache (die Zielsprache) umwandelt.
Compiler werden verwendet, um High-Level-Quellcode in Low-Level-Zielcode (wie Assemblersprache, Objektcode oder Maschinencode) umzuwandeln, während die Programmfunktionalität erhalten bleibt.
Der Compiler ist ein unverzichtbares Tool für die moderne, praktische Computerprogrammierung. Er ermöglicht es Programmierern, in einer lesbaren höhere Programmiersprache zu arbeiten und ihren Quellcode anschließend in einen ausführbaren Zielcode umzuwandeln. Compiler unterstützen Softwareentwickler auch dabei, effiziente ausführbare Programme mit verbesserter Sicherheit, Stabilität und Portabilität zu erstellen. Dies liegt daran, dass Compiler dabei helfen, Fehler zu identifizieren und zu beheben, wodurch portable ausführbare Anwendungen entstehen.
Obwohl alle Compiler hochsprachigen Code in niedrigsprachigen, ausführbaren Code umwandeln, werden für verschiedene Programmiersprachen und Anwendungen unterschiedliche Compiler verwendet. Ein Cross-Compiler wird beispielsweise verwendet, um Code für einen anderen Typ von CPU oder Betriebssystem zu erstellen als den, auf dem er ausgeführt wird.
Wenn der ideale Compiler nicht verfügbar ist oder noch nicht erstellt wurde, wird ein temporärer Bootstrap-Compiler verwendet, um einen dauerhafteren Compiler zu kompilieren, der besser für die Kompilierung einer bestimmten Programmiersprache optimiert ist.
Eine kurze Liste weiterer verwandter Software umfasst:
Branchen-Newsletter
Bleiben Sie mit dem Think-Newsletter über die wichtigsten – und faszinierendsten – Branchentrends in den Bereichen KI, Automatisierung, Daten und darüber hinaus auf dem Laufenden. Weitere Informationen finden Sie in der IBM Datenschutzerklärung.
Ihr Abonnement wird auf Englisch geliefert. In jedem Newsletter finden Sie einen Abmeldelink. Hier können Sie Ihre Abonnements verwalten oder sich abmelden. Weitere Informationen finden Sie in unserer IBM Datenschutzerklärung.
In der Praxis kann die Verwendung eines Compilers so einfach sein wie die Eingabe eines Befehls in eine Befehlszeile in einem beliebigen Linux-System (oder einem gleichwertigen System), wobei die ausführbare Compiler-Datei und die zu kompilierenden Quelldateien angegeben werden. Dieser Befehl weist das System an, den Quellcode zu verarbeiten, ihn in einen Zielmaschinencode zu kompilieren und die erforderlichen Objektdateien zu erzeugen, um ein ausführbares Programm zu erstellen.
Open-Source-Compiler wie die GNU Compiler Collection (GCC) – eine robuste C-Compiler-Sammlung, die häufig verwendet wird, um C-Code in C-Programme zu kompilieren – oder das alternative Clang sind auf Repositorys wie GitHub verfügbar. Andere Compiler können frei installiert oder von einer Vielzahl von Händlern erworben werden. Sie können auch in gängige integrierte Entwicklungsumgebungen (IDEs) eingebunden werden, die verschiedene Dienstprogramme für die Softwareentwicklung bündeln, darunter Texteditoren, API-Dokumentation und Debugging-Tools.
Unabhängig vom verwendeten Compiler umfasst der Prozess der Code-Kompilierung die Überprüfung des Quellcodes auf verschiedenen Ebenen der Analyse, Optimierung und schließlich der Codegenerierung. Der Quellcode durchläuft nacheinander die verschiedenen Analyseebenen und wird in jedem Schritt des Prozesses ausgewertet.
Wenn der Compiler irgendwelche Probleme mit dem ursprünglichen Quellcode erkennt, gibt er möglicherweise eine Fehlermeldung zurück, die Entwickler auffordert, identifizierte Fehler zu beheben, bevor sie mit dem Kompilieren des restlichen Codes fortfahren. Im Allgemeinen führen Compiler die folgenden Schritte durch:
Einige Compiler halten sich möglicherweise nicht strikt an die vorstehende Struktur. Obwohl einige Compiler mehr oder weniger Schritte enthalten können, lassen sich alle Phasen der Kompilierung einer von drei Stufen zuordnen: einem Frontend, einem Middleend und einem Backend.
Diese dreistufige Struktur ermöglicht Compilern einen modularen Ansatz. Es ermöglicht die Kombination mehrerer Frontends für verschiedene Sprachen mit Backends für verschiedene CPUs, wobei die Optimierungsfunktionen verschiedener anwendbarer Middle-Ends gemeinsam genutzt werden.
Die drei Phasen eines Compilers lassen sich wie folgt unterteilen:
Compiler sind zwar nicht explizit notwendig, um brauchbaren Code zu erzeugen, aber die große Vielfalt und Komplexität sowohl der Codierung als auch der Maschinenumgebungen machen Compiler zu einer praktischen Notwendigkeit für die Erstellung ausführbarer Software. Dies sind die vier Hauptvorteile der Verwendung von Softwarecompilern.
Höhere Programmiersprachen verwenden eine Syntax und Schlüsselwörter, die denen der gesprochenen Sprachen näher sind, was die Bedienung für Entwickler wesentlich erleichtert. Compiler wandeln diesen menschenlesbaren Code in den komplexeren Maschinencode um, der zum Ausführen optimierter Anwendungen erforderlich ist.
Einige Beispiele für hochrangige Sprachen sind die folgenden Sprachen:
Compiler tragen zur Verbesserung der Effizienz bei, indem sie High-Level-Code in ausführbaren Maschinencode umwandeln. Die Ausgabe des Compilers wird mit einer .exe-Dateierweiterung gespeichert, die dann direkt von einem Computer ausgeführt werden kann. Dank des Compilers wird das Schreiben eines ausführbaren Programms zu einer einmaligen Aufgabe.
Nach der Fertigstellung kann der kompilierte Code so oft wie nötig ausgeführt werden. Dieser Prozess trägt dazu bei, dass Programme im Allgemeinen schneller und effizienter ausgeführt werden, da bestimmte Anwendungen oder Teile von Anwendungen getrennt von Laufzeitsoftwareaufgaben ausgeführt werden können.
Nicht alle Systeme können alle Arten von Programmcode ausführen. Compiler werden verwendet, um die von Entwicklern bevorzugten Codetypen in die Codetypen zu konvertieren, die Systeme für ihren Betrieb benötigen. Auf diese Weise verbessern Compiler die Portabilität von Programmen, indem sie Software in eine Vielzahl kompatibler Sprachen konvertieren, die sich leicht speichern, übertragen und auf verschiedenen Betriebssystemen und Hardwarearchitekturen ausführen lassen.
Während des Kompilierungsprozesses können Compiler eingesetzt werden, um Softwarefehler und -mängel zu identifizieren und zu beheben, was zu stabileren und besser optimierten Programmen führt. Compiler können auch zur Verbesserung der Softwaresicherheit beitragen, indem sie Speicherfehler wie Pufferüberläufe verhindern und Warnungen ausgeben, wenn potenzielle Speicherprobleme erkannt werden.
Während Compiler verwendet werden, um Quellcode in ausführbaren Maschinencode umzuwandeln, sind Interpreter eine andere Art von Programm, die ähnliche Funktionen bieten können, jedoch über einen anderen Mechanismus.
Anstatt den Quellcode zu konvertieren, führen Interpreter den Quellcode entweder direkt aus oder verwenden einen Zwischencode, der als Bytecode bekannt ist. Dabei handelt es sich um eine plattformunabhängige Low-Level-Darstellung des Quellcodes. Bytecode dient als Vermittler zwischen menschenlesbarem Quellcode und Maschinencode, konzipiert für die Ausführung durch eine virtuelle Maschine (VM) statt direkt auf der Hardware eines Computers.
Theoretisch kann jede Programmiersprache entweder mit einem Compiler oder einem Interpreter ausgeführt werden. Einzelne Programmiersprachen eignen sich jedoch in der Regel besser für die Kompilierung oder Interpretation.
In der Praxis kann die Unterscheidung zwischen Compiler- und Interpretersprachen manchmal verschwimmen – ebenso wie die Unterscheidung zwischen Compilern und Interpretern selbst – da beide Arten von Programmen überlappende Funktionen aufweisen können. Während einige Sprachen eher kompiliert und andere eher interpretiert werden, ist es möglich, einen Compiler für eine Sprache zu schreiben, die üblicherweise interpretiert wird und umgekehrt.
Höhere Programmiersprachen werden in der Regel mit Blick auf eine bestimmte Art der Konvertierung entwickelt – entweder Kompilierung oder Interpretation –, jedoch handelt es sich hierbei eher um Empfehlungen als um strenge Einschränkungen. Beispielsweise wird BASIC häufig als interpretierte Sprache und C als kompilierte Sprache bezeichnet, jedoch existieren Compiler für BASIC ebenso wie C-Interpreter.
Der Hauptunterschied zwischen Interpretern und Compilern liegt im Timing und in der Optimierung. Beide Programme versuchen, Quellcode in Zielcode umzuwandeln, der zunächst funktionsfähig ist und anschließend optimiert wird.
Je nach Betriebsumgebung kann kompilierter oder interpretierter Code besser geeignet sein, um unter Berücksichtigung der Hardwareleistung, des Arbeitsspeichers und der Speicherkapazität effizient ausgeführt zu werden. Abhängig von den Einschränkungen eines bestimmten Programms, einer Anwendung oder der Hardware kann entweder die Kompilierung, die Interpretation oder eine Kombination aus beidem die besten Ergebnisse erzielen.
Daher kann die Interpretation die Kompilierung nicht vollständig ersetzen, aber sie kann die Kompilierungsaufgaben durch einen schrittweisen Umstellungsprozess in den Hintergrund verlagern. Compiler verwenden eine Ahead-of-Time-Konvertierungsstrategie (AOT), die den Quellcode vollständig in Zielcode umwandelt, bevor eine ausführbare Datei erstellt wird.
Interpreter hingegen führen entweder Code direkt aus, wenn eine Anwendung dies erfordert, oder verwenden Bytecode als Zwischenform, um den ausführbaren Quellcode für die virtuelle Maschine auszugeben. So bieten Interpreter zwar gewisse Geschwindigkeitsvorteile und Flexibilität, jedoch muss gegen Ende des Ausführungsstacks eine Reihe direkt ausführbarer Maschinenbefehle bereitgestellt werden.
In einigen Fällen, in denen eine geringe Effizienz vorrangig ist, können spezielle Interpreter aufgrund ihrer Fähigkeit zur Just-in-Time-Konvertierung (JIT) gegenüber Compilern vorzuziehen sein. JIT ist eine Strategie, bei der Teile des Quellcodes in Zielcode kompiliert und in einem Speicherpuffer für die sofortige Ausführung gespeichert werden. Die JIT-Interpretation kompiliert Code bei Bedarf und kombiniert dabei die Effizienz einer einmaligen Kompilierung durch einen herkömmlichen Compiler mit der Flexibilität, Code wiederholt auszuführen – oft schneller als Standard-Bytecode-Interpreter.
Da jedoch moderne Trends hin zur JIT-Kompilierung zusammen mit situationsabhängiger Bytecode-Interpretation zunehmen, werden viele Compiler so konzipiert, dass sie sowohl Kompilierungs- als auch Interpretierungsfunktionen bieten. Diese Überschneidung lässt die Grenzen zwischen diesen beiden Kategorien weiter verschwimmen.
IBM Cloud Infrastructure Center ist eine mit OpenStack kompatible Softwareplattform für die Verwaltung der Infrastruktur von Private Clouds auf IBM zSystems und IBM LinuxONE.
Entdecken Sie Server, Speicher und Software für die Hybrid-Cloud- und KI-Strategie Ihres Unternehmens.
Finden Sie die richtige Cloud-Infrastrukturlösung für Ihre Geschäftsanforderungen und skalieren Sie Ressourcen nach Bedarf.