1. Kennenlernen des Compilers
Der Computer versteht keine natürliche Sprache. Er versteht nicht einmal Programmiersprachen direkt. Er versteht nur Programme, geschrieben in Maschinencode — bestehend aus Nullen und Einsen. Menschen denken jedoch in Worten und Ideen, und natürlich ist es für sie schwer, komplette Programme nur aus 0 und 1 zu schreiben.
00100100 wird als Dezimalzahl
36 oder als Zeichen
$ interpretiert
Deshalb entstanden Programmiersprachen wie C++. Sie fungieren als eine Art „Übersetzer“: Der Programmierer kann Befehle in einer für ihn verständlichen Sprache schreiben, anstatt eine lange Kette von Prozessoranweisungen zu verfassen.
Aber es gibt einen Haken. Der Computer versteht C++ trotzdem nicht direkt! Wenn man ihm einfach eine Datei mit Code gibt, zuckt er mit den Schultern und tut nichts. Genau für diesen Fall gibt es den Compiler.
Was ist ein Compiler?
Ein Compiler ist ein spezielles Programm, das Code kompiliert: es übersetzt C++-Code in für den Computer verständlichen Code. Er nimmt den Text in C++, analysiert ihn, prüft auf Fehler und wandelt ihn in Maschinencode um (in der Regel als ausführbare Datei).
- Programm in C++
-
Compiler
- Programm, bestehend aus Maschinencode
Man kann sich den Compiler wie einen strengen Lehrer vorstellen, der:
- die Sätze genau überprüft (hast du einen Fehler gemacht?),
- dafür sorgt, dass Regeln eingehalten werden (z. B. gültige Variablennamen, Semikolons, Klammern …),
- und erst dann den Kontakt zum Computer zulässt!
Der Compiler ist noch klüger
Heutige C++-Compiler sind noch intelligenter — sie können nicht nur übersetzen, sondern auch den Code optimieren, Fehlerhinweise geben und sogar Verbesserungsvorschläge machen (über Warnungen — warnings). Und noch vieles mehr.
Und der Reihe halber: für die bequeme und korrekte Erstellung eines größeren Programms erfolgt die Kompilierung in der Regel nicht „in einem magischen Schritt“, sondern mindestens in mehreren Phasen:
- Zuerst verarbeitet der Präprozessor Direktiven wie #include.
- Dann übersetzt der Compiler den C++-Code in Objektcode (teilweise fertige „Stücke“ des Programms).
- Und anschließend linkt (der Linker) diese Stücke und die eingebundenen Bibliotheken zu einer ausführbaren Datei zusammen.
Wenn Sie einen leistungsfähigen Prozessor und aktivierte Optimierungen haben, kann der Compiler Maschinencode erzeugen, der die Eigenschaften Ihrer Plattform und die gewählten Build-Optionen berücksichtigt. Wichtig ist jedoch die einfache Idee zu merken: C++ wird üblicherweise direkt in Maschinencode kompiliert, und diese ausführbare Datei wird dann ausgeführt.
flowchart TD
SRC["Quellcode .cpp Dateien"]:::source
PP["Präprozessor verarbeitet #include und #define"]:::stage
CC["Compiler übersetzt C++ → Objektcode Findet Fehler, gibt warnings"]:::stage
LN["Linker verbindet Objektcode + bindet Bibliotheken ein"]:::stage
EXE["Ausführbare Datei .exe"]:::artifact
RUN(["▶ Ausführung Fertiger Maschinencode wird direkt ausgeführt"]):::run
LIB["Bibliotheken"]:::lib
DEV["Entwickler behebt Fehler"]:::dev
SRC --> PP --> CC --> LN --> EXE --> RUN
CC -.->|"⚠️ warnings & Fehler"| DEV
LIB --> LN
classDef source fill:#f59e0b,color:#1c1917,stroke:none
classDef stage fill:#3b82f6,color:#fff,stroke:#1d4ed8,stroke-width:2px
classDef artifact fill:#8b5cf6,color:#fff,stroke:#6d28d9,stroke-width:2px
classDef lib fill:#64748b,color:#fff,stroke:none
classDef run fill:#22c55e,color:#fff,stroke:none
classDef dev fill:#fde68a,color:#1c1917,stroke:#f59e0b,stroke-width:1px
2. Kompilierungsfehler
Geschwindigkeit und Optimierung sind für uns vorerst nicht so wichtig; wichtiger ist, dass der Compiler Ihr Programm auf Fehler prüft. Er kontrolliert den Code auf Korrektheit und lässt ihn nicht weiter, wenn er auch nur einen kleinen Fehler findet.
Beispiel für einen Fehler:
Sie versuchen, einer Variablen eine Zahl zuzuweisen, die nur Text speichern kann.
#include <string>
int main() {
std::string userName = 42; // Oh! So geht das nicht.
}
Der Compiler meldet sofort einen Typfehler (Formulierung abhängig vom Compiler), etwa: „keine passende Konvertierung von int nach std::string“.
Ein anderes Beispiel — ein Tippfehler im Namen std::cout:
#include <iostream>
int main() {
std::coutt << "Hallo!\n"; // Fehler im Namen
}
Der Compiler wird etwas sagen wie: „coutt ist kein Mitglied von std“ — prüfen Sie die Syntax!
Wie liest man Fehlermeldungen?
Die meisten Compiler zeigen an, wo im Code der Fehler ist: normalerweise Datei, Zeilennummer und oft sogar die Spaltennummer sowie eine Fehlermeldung. Haben Sie keine Angst vor Fehlern: jeder von ihnen ist ein Schritt zur Aufklärung und zum Bestehen Ihres inneren "Bosses".
3. Typische Kompilierungsfehler
expected bedeutet: „ich habe hier das Zeichen X erwartet, es ist aber nicht da“. Meistens ist das:
expected ';' — Semikolon vergessen
Defekter Code:
#include <iostream>
int main() {
std::cout << "Hello!\n"
return 0;
}
Anweisungen müssen mit ; enden. Der Compiler erreicht return und erwartet noch immer ein ;. Korrektur:
std::cout << "Hello!\n";
expected '}' — Block nicht geschlossen
Wenn Sie } vergessen, meckert der Compiler normalerweise am Ende der Datei.
int main() {
std::cout << "Start\n";
return 0;
// keine }
Schließen Sie den Block einfach:
}
Tipp: Richten Sie die Einrückungen ordentlich aus — so findet man eine fehlende Klammer leichter.
expected ')' oder expected '(' — Problem mit Klammern
int main( {
Richtig wäre:
int main() {
Klammern müssen paarweise geöffnet und geschlossen werden.
not declared — Name nicht gefunden
Der Compiler sagt: „ich weiß nicht, was das ist“. Sie haben möglicherweise std:: vergessen
cout << "Hi\n";
Richtig:
std::cout << "Hi\n";
cout befindet sich im Namensraum std.
#include vergessen <iostream>
int main() {
std::cout << "Hi\n";
}
Fügen Sie hinzu:
#include <iostream>
Ohne #include muss der Compiler nicht wissen, was std::cout ist.
4. Kommentare
Stellen Sie sich vor: Sie schreiben ein komplexes Programm. Alles funktioniert, Sie fühlen sich wie ein Genie! Aber einen Monat später öffnen Sie den Code wieder und... verstehen nichts mehr. Zwei Codezeilen hier, eine merkwürdige Variable dort. Im Kopf nur: „Das musste irgendjemand anderes geschrieben haben, aber nicht ich!“. Hier kommen Kommentare zur Rettung.
Kommentare sind wie Notizen am Rand eines Lehrbuchs oder Aufkleber am Kühlschrank („Bier. Nicht trinken. Morgen!“). Der Compiler ignoriert sie, Menschen nicht. Kommentare erklären den Sinn des Codes, markieren wichtige Details und erlauben es, Codeabschnitte vorübergehend zu deaktivieren, ohne sie zu löschen.
Wichtig: Der Compiler „versteht“ den Sinn Ihrer Kommentare nicht — für ihn sind es einfach Texte, die übersprungen werden müssen.
Einzeilige Kommentare
In C++ gibt es zwei Arten von Kommentaren — einzeilige und mehrzeilige. Einzeilige beginnen mit zwei Schrägstrichen // und reichen bis zum Zeilenende. Alles, was nach // steht, gilt als Kommentar und wird vom Compiler völlig ignoriert.
Beispiel:
#include <iostream>
int main() {
std::cout << "Hallo, Welt!\n"; // Dies gibt eine Begrüßung auf dem Bildschirm aus
}
Hier ist // Dies gibt eine Begrüßung auf dem Bildschirm aus ein Kommentar. Wenn im Code etwas unklar erscheint, schreiben Sie so eine Erklärung!
Noch ein Beispiel:
int main() {
int x = 42; // Wert des Alters des Programmierers
}
Man kann einzeilige Kommentare auch auf separaten Zeilen schreiben:
#include <string>
int main() {
// Initialisierung der Variable mit dem Benutzernamen
std::string userName = "John";
}
Fast wie Regieanweisungen in einem Drehbuch: der Kommentar erklärt, wozu die Zeile dient.
Mehrzeilige Kommentare
Was, wenn Sie viel zu sagen haben? Eine ganze Geschichte? Dafür gibt es mehrzeilige Kommentare, die mit /* beginnen und mit */ enden. Alles dazwischen wird vom Compiler ignoriert, selbst wenn es mehrere Zeilen sind.
Beispiel:
#include <iostream>
int main() {
/*
Hier geben wir dem Benutzer eine Aufforderung aus.
Falls der Name fehlt, kann man in anderen Programmen "Gast" schreiben.
*/
std::cout << "Geben Sie Ihren Namen ein:\n";
}
Oder so:
int main() {
int age = 18; /* Anfangswert für das Alter
eines neuen Benutzers */
}
Achtung: Sie können mehrzeilige Kommentare nicht ineinander verschachteln. Versuchen Sie nicht, den Compiler auszutricksen — das funktioniert nicht.
Illustration:
| Typ | Syntax | Beispiel |
|---|---|---|
| Einzeilig | |
|
| Mehrzeilig | |
|
5. Beispiele aus dem Leben
„Deaktivierung“ einer Codezeile:
Manchmal möchte man zeitweise einen Codeabschnitt nicht ausführen. Kommentare sind hier genau richtig:
// std::cout << "Text, der vorübergehend nicht benötigt wird\n";
Die Zeile bleibt erhalten, aber der Compiler „sieht“ sie nicht.
Markierungen TODO und FIXME
Programmierer sind auch nur Menschen und schreiben sich manchmal selbst Erinnerungen, dass der Code noch unvollständig ist oder einen Fehler enthält. Dafür schreibt man oft:
// TODO: Überprüfung auf leere Eingabe einbauen
// FIXME: diese Funktion berechnet die Summe falsch
Viele Editoren und IDEs heben solche Stichworte sogar hervor!
Programmierer scherzen
Und natürlich findet man manchmal sehr unterhaltsame Kommentare im Code:
// Ich übernehme keine Verantwortung für diesen Code. Man hat mich gezwungen, ihn gegen meinen Willen zu schreiben.
// Liebes Ich aus der Zukunft! Bitte verzeih mir für diesen Code.
// Wenn ich das noch einmal sehe, werde ich gezwungen sein, mit einer Waffe zur Arbeit zu kommen.
// Falls diese Bedingung jemals zutrifft, bitte benachrichtige mich telefonisch unter xxx-xx-xx gegen Belohnung.
// Lieber Programmierer:
//
// Wenn du diese Unterroutine fertig optimiert hast
// und erkennst, wie groß der Fehler war,
// erhöhe bitte den Zähler unten als Warnung
// für den nächsten Kerl:
//
// anzahl_gebrauchter_stunden_hier = 42
// Als ich anfing, das zu schreiben, verstanden nur Gott und ich, was ich tat.
// Jetzt versteht nur noch Gott
// Manchmal habe ich das Gefühl, der Compiler ignoriert alle meine Kommentare
// Ich widme meinen gesamten Code, meine ganze Arbeit meiner Frau Darlin, die
// mich, unsere drei Kinder und den Hund ernähren muss,
// wenn das in Produktion geht.
Ja, Kommentare können sehr lustig sein. Schließlich schreiben sie lebende Menschen.
GO TO FULL VERSION