Begriff
Compiler vs. Interpreter
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Computer verstehen nur Nullen und Einsen (Maschinencode).
Du schreibst aber Englisch (if (x > 5)).
Jemand muss übersetzen.
Der Compiler ist wie ein Buch-Übersetzer.
Er nimmt deinen ganzen Code, liest ihn komplett, findet alle Fehler, und schreibt ein neues Buch in Maschinensprache (.exe).
Erst danach kannst du das Programm starten.
Vorteil: Das fertige Programm ist extrem schnell.
Beispiele: C++, Go, Rust.
Merksatz: Ein Programm, das Quellcode einer Hochsprache vollständig in Maschinencode (oder Bytecode) übersetzt, bevor das Programm ausgeführt wird.
Workflow in C++:
- Code schreiben (
main.cpp). - Kompilieren:
g++ main.cpp -o main.exe. (Dauert Sekunden bis Minuten). - Ausführen:
./main.exe.
Wenn du einen Syntaxfehler hast, meckert der Compiler bei Schritt 2 und bricht ab. Das Programm wird gar nicht erst erstellt.
1. Phasen eines Compilers
- Lexing (Scanner): Zerlegt Text in Wörter ("Tokens").
if,(,x. - Parsing: Baut den Grammatik-Baum (AST - Abstract Syntax Tree). Versteht die Struktur.
- Semantic Analysis: Macht es Sinn? ("Du addierst String mit Integer"). Hier fliegen Typ-Fehler.
- Optimization: Schmeißt sinnlosen Code weg ("Dead Code Elimination"), rollt Schleifen aus. (Hier passiert die Magie für Speed).
- Code Generation: Schreibt Assembler/Maschinencode für die CPU (x86 oder ARM).
2. Ahead-of-Time (AOT) vs. JIT
Klassische Compiler sind AOT (Vorher).
Java und C# sind Hybriden. Sie kompilieren zu Bytecode (Zwischensprache).
Beim Starten übersetzt die Virtual Machine (JVM) den Bytecode in echten Maschinencode (Just-in-Time / JIT).
Vorteil: "Write Once, Run Anywhere". Die .class Datei läuft auf Windows und Linux.
3. Transpiler (Source-to-Source)
Ein "Compiler", der von einer Hochsprache in eine andere Hochsprache übersetzt. Berühmtestes Beispiel: TypeScript. Es wird nicht zu Maschinencode kompiliert, sondern zu JavaScript. Browser verstehen nur JS.
1. LLVM und die drei Schichten
Früher (z.B. alter GCC) baute man Compiler als riesige Monolithen (C++-Code rein, Intel-Maschinencode raus). Wollte man eine neue Sprache (Rust) addieren, musste man fast von vorn beginnen. Heute nutzen fast alle modernen Programmiersprachen LLVM (Low Level Virtual Machine). Es trennt den Compiler radikal in Front-End, Optimizer, und Back-End:
- Das Front-End (z.B. Clang für C++ oder rustc für Rust) liest den Code und konvertiert ihn in eine universelle Sprache, die LLVM IR (Intermediate Representation).
- Der Optimizer (das LLVM-Herzstück) hat keine Ahnung, ob der Code C oder Swift war. Er optimiert nur diese rohe IR gigantisch auf Speed.
- Das Back-End nimmt die perfekte IR, und baut Maschinencode exakt für deinen Chip (x86, ARM, WebAssembly).
2. Symbol Tables & Name Mangling
Woher weiß das Programm zur Laufzeit, welche Speicheradresse die Variable score hat? Gar nicht.
Der Compiler opfert alle schönen Text-Namen auf dem Altar der Geschwindigkeit.
Während der Kompilierung führt er eine Symbol Table, eine riesige Map, auf der steht: "score = Hex-Adresse 0x40120A".
In Sprachen mit Function Overloading (Zwei Funktionen heißen print(), eine nimmt Int, eine String), betreibt der Compiler Name Mangling. Er zermatscht den Namen vor dem Linken in etwas Unleserliches, um Konflikte zu umgehen: print(int) wird intern zu _Z5printi, print(string) zu _Z5prints.
3. Just-In-Time (JIT) Profiling Magic
Warum kann ein JIT-Kompilierter Java-Code manchmal auf Dauer schneller laufen als pures C++ (AOT)?
Wegen Runtime Profiling.
Ein C++ Compiler macht bei der Kompilierung einen Schuss ins Blaue, wie User den Code später nutzen.
Die JVM (Java) beginnt als langsamer Interpreter. Dabei misst sie wochenlang mit: "Die calculate()-Funktion wird 1000 mal pro Sekunde gerufen, und der Parameter x ist zu 99% immer 5!".
Der JIT-Compiler springt an, wendet aggressives Inlining und CPU-Caching exakt für den Wert 5 an und baut echten Maschinencode, der für das tatsächliche Echtwelt-Verhalten des Users "warm"-optimiert wurde.
Quick-Check
Warum kompiliert Python nicht?
Python ist (meistens) interpretiert. Es gibt keinen Schritt 2. Das Programm startet sofort, aber läuft langsamer.Cross-Compilation?
Ich arbeite auf einem Mac, will aber eine.exefür Windows bauen. Der Compiler muss Code für eine fremde CPU/OS generieren. Schwierig, aber Go macht es sehr einfach (GOOS=windows go build).Linker?
Nach dem Kompilieren hast du viele kleine Objekt-Dateien (.o). Der Linker klebt sie zusammen zu einer einzigen ausführbaren Datei und bindet Bibliotheken ein.