Frage zur Arbeit des Compilers
-
Hallo!
Momentan beschäftige ich mich mit dem C++-Compiler und dem Präprozessor.
Leider gibts einige Unsicherheiten, die auch nirgendwo erklärt sind:1.Ist es richtig, dass alle Deklarationen von Variablen und Klassen schon vor dem Programmablauf dem Compiler bekannt gemacht werden ? Wenn ich z.B. schreibe
int a;
int b = 5;class CPlayer
{
// ....
}2. Bei #include-Direktiven soll ja vom Präprozessor einfach der Code des entsprechneden Moduls an die Stelle der Direktive gesetzt werden.
Wenn man nun z.B. schreibt
using namespace std;
int main()
{
cout << "xyz" << endl;
}#include <iostream>
Dann funktioniert das Programm ja nicht. Aber es ist doch richtig, dass:
1. Der Präprozessor durch das Programm läuft und mein #include <iostream> durch die entsprechenden Funktionen ersetzt
2. Der Compiler das Programm kompiliert und dann nicht über den cout-Befehl verfügt, weil dieser erst unterhalb des "#include <iostream>" verfügbar ist ? Das "#include <iostream>" wurde ja erst geshriebven, nachdem es schon eingesetzt wurde.3. Bei der #define-Direktive: die ist ja auch ein Präprozessor-Befehl.
Wenn man nun schreibt:#define C 10
int main()
{
cout << C << endl;
cout << A << endl;
}#define A 15
Dann gibt es eine Fehlermeldung. Liegt es daran, dass der Präprozessor sozusagen das Programm von oben nach unten durchläuft und die Textersetzungen nur vornimmt, wenn ihm die Konstante (also A bzw. C) schon bekannt ist ?
Herzliche Grüße und Danke im Voraus
Monadic512
-
Zu Frage 1
int a; int b = 5; class CPlayer { // .... }Zu Frage 2
using namespace std; int main() { cout << "xyz" << endl; } #include <iostream>Zu Frage 3
#define C 10 int main() { cout << C << endl; cout << A << endl; } #define A 15Herzliche Grüße und Danke im Voraus
-
- Nur die Deklaration muss vor dem Einsatz bekannt sein. Aber der Linker muss die Definition eines eingesetzten Bezeichners sehen.
- Ich weiss nicht wie das im Präprozessor-Inneren aussieht aber du kannst sicher sein, dass es einen Fehler hervorruft.
- Richtig.
-
1. Es gilt Variablen so lokal wie möglich zu deklarieren. Globale Variablen sind kein guter Programmierstil und bringen häufig schwer findbare Fehler mit sich.
2. Ja, du hast die Vorgehensweise des Präprozessors anscheinend gut verstanden. Denn genau deshalb funktioniert es nicht. Dabei ist es aber etwas zu allgemein gesagt, das der Präprozessor nur die Funktionen einfügt. Tatsächlich fügt er den gesamten Inhalt der Datei iostream ein. Du kannst auch selber eine separate Datei erstellen und mit #include in dein Programm einbinden. So kann man sein Programm gliedern. Die Klasse CPlayer könnte dann z.B. eine eigene Datei bekommen. In dem Fall solltest du dich noch nach Include-Guards umschauen.
3. Auch hier hast du das Problem richtig erkannt. Der Präprozessor kann nur Dinge ersetzen, die ihn zu diesem Zeitpunkt auch bekannt sind. Bei A ist das nicht der Fall, weshalb der Compiler A für eine Variable hält, die aber auch nicht deklariert ist. Das Programm kompiliert also nicht.
-
Monadic512 schrieb:
Leider gibts einige Unsicherheiten, die auch nirgendwo erklärt sind:
Lass uns sagen, deren Erklärung dur nirgendwo gefunden hast.
Monadic512 schrieb:
1.Ist es richtig, dass alle Deklarationen von Variablen und Klassen schon vor dem Programmablauf dem Compiler bekannt gemacht werden ?
Sowohl der Compiler als auch der Sourcecode hat mit dem eigentlichen Programmablauf und nicht direkt zu tun. Der Compiler liest den Sourcecode (inclusive der Variablendeklarationen) und generiert daraus Objektdateien. Der Linker generiert daraus die ausführbare Datei. Der Programmablauf startet, wenn du die ausführbare Datei ausführst. Das kann auf einem anderen Rechner und sehr viel später passieren, ist also ziemlich entkoppelt von Variablendeklarationen etc. (Die Namen der Variablen sind in den ausführbaren Dateien auch nicht mehr enthalten, falls es darum ging).
Monadic512 schrieb:
2. Bei #include-Direktiven soll ja vom Präprozessor einfach der Code des entsprechneden Moduls an die Stelle der Direktive gesetzt werden.
Wenn man nun z.B. schreibt
using namespace std;
int main()
{
cout << "xyz" << endl;
}#include <iostream>
Dann funktioniert das Programm ja nicht. Aber es ist doch richtig, dass:
1. Der Präprozessor durch das Programm läuft und mein #include <iostream> durch die entsprechenden Funktionen ersetzt
2. Der Compiler das Programm kompiliert und dann nicht über den cout-Befehl verfügt, weil dieser erst unterhalb des "#include <iostream>" verfügbar ist ? Das "#include <iostream>" wurde ja erst geshriebven, nachdem es schon eingesetzt wurde.Richtig. In der main oben weiß der Compiler nicht, was mit cout gemeint ist. Du sagst es ihm erst hinterher, wenn er schon längst nicht mehr weiß, dass er da vorher drüber gestolpert ist.
3. Bei der #define-Direktive: die ist ja auch ein Präprozessor-Befehl.
Wenn man nun schreibt:#define C 10
int main()
{
cout << C << endl;
cout << A << endl;
}#define A 15
Dann gibt es eine Fehlermeldung. Liegt es daran, dass der Präprozessor sozusagen das Programm von oben nach unten durchläuft und die Textersetzungen nur vornimmt, wenn ihm die Konstante (also A bzw. C) schon bekannt ist ?
Richtig. Nach dem PP steht in obigem Programm folgendes:
int main() { cout << 10 << endl; cout << A << endl; }(Whitespaces hab ich der Übersicht wegen gelassen. Der PP schrumpft die auch alle zusammen.)
-
Monadic512 schrieb:
Momentan beschäftige ich mich mit dem C++-Compiler und dem Präprozessor.
Leider gibts einige Unsicherheiten, die auch nirgendwo erklärt sind
