WikiDer > Präprozessor

Preprocessor

In dem Informatik ist ein Präprozessor ein Computer Programm die eine Ausgabe erzeugt, die als Eingabe für andere Programme verwendet wird. Die Verarbeitung von Daten durch einen Präprozessor wird zu Vorverarbeitung erwähnt. Ein Präprozessor wird häufig verwendet, um vorbereitende Operationen an Daten durchzuführen, die dann weiterverarbeitet werden. Die Operationen, die ein Präprozessor an den Daten ausführt, können unterschiedlich sein: Einige führen nur einfache Operationen durch Makros oder Ersetzungen, während andere die Daten vollständig in die gewünschte Ausgabe umwandeln.

Präprozessoren werden häufig als erster Verarbeitungsschritt auf dem Quellcode von a Programmiersprache, bevor Sie es mit a . bearbeiten Compiler. In einigen Sprachen, wie z C und C Tatsächlich ist der Präprozessor ein unverzichtbarer Bestandteil, der in fast jedem Programm verwendet wird.

Lexikalische Vorverarbeitung

Ein lexikalischer Präprozessor führt Operationen auf der Ebene von lexikalische Analyse: Dieser Schritt erfolgt vor dem analysieren und ein lexikalischer Präprozessor führt oft nur einfache Ersetzungen durch oder ersetzt eine Zeile Token durch eine andere Reihe Token. Diese Operationen können vom Benutzer spezifiziert werden, beispielsweise indem spezielle Anweisungen in die Daten aufgenommen werden.

Vorverarbeitung in C/C

Der am häufigsten verwendete Präprozessor ist cpp, der Präprozessor von C und C . Es kann allgemeine Operationen wie das Einfügen von Quellcode aus einer anderen Datei, das Ausführen von Makros und die bedingte Kompilierung ausführen. Präprozessoranweisungen beginnen mit '#'.

#einschließen

Diese Präprozessoranweisung wird häufig verwendet, um eine Datei in die Datei einzufügen, die die Anweisung enthält:

#einschließen"..."

oder

#einschließen<...>

Der gesamte Inhalt der benannten Datei wird dort eingefügt, wo sich diese Anweisung befindet. Diese Dateien enthalten oft (fast immer) Definitionen für Bibliotheksfunktionen oder Datentypen. Diese müssen eingefügt werden, bevor sie verwendet werden können. Ein #include steht daher normalerweise am Anfang einer Datei. Diese eingefügten Dateien werden Header-Dateien benannt, wie sie am Anfang der Datei stehen ('head' auf Englisch). Beispiele dafür sind #include und #include die jeweils für Input/Output und mathematische Berechnungen verwendet werden.

Diese Methode zur Wiederverwendung von Code ist einfach, aber auch langsam und ineffizient, da eine Überprüfung erforderlich ist, um zu vermeiden, dass eine Datei mehr als einmal eingefügt wird. Seit den 1970er Jahren sind bessere Techniken zur Wiederverwendung von Code bekannt: Java und Gemeinsame Lisp Pakete haben, Pascal hat Einheiten und Modul, OCaml, Haskell und Python haben Module und d, als Ersatz für C und C konzipiert, hat Importe.

#definieren

Mit #define kann eine Konstante oder ein Makro definiert werden. Diese werden während der Vorverarbeitung an der Stelle platziert, an der der Wert oder die Funktion verwendet wird (die im Einklang einer Funktion/Konstante). Wenn das Makro Parameter hat, werden diese an der richtigen Stelle ersetzt. Auf diese Weise kann ein Makro wie eine (Kurz-)Funktion verwendet werden. Der übliche Grund dafür besteht darin, die zusätzlichen Schritte eines Funktionsaufrufs zu vermeiden. Bei kurzen Funktionen sind diese zusätzlichen Schritte (die Überkopf) wirkt sich nachteilig auf die Leistung des Programms aus, wodurch es besser wird, die Funktion einzubinden.

Ein Beispiel:

#define max(a,b) a>b?a:b

Dies definiert a max Makro, das den größeren der beiden Parameter zurückgibt. Dies kann nun wie eine reguläre Funktion verwendet werden. Nach der Vorverarbeitung ändert sich Folgendes:

z=max(X,ja);

also hinein:

z=X>ja?X:ja;

Obwohl dies eine wichtige Technik in C ist, ist sie auch langsam, ineffizient und hat einige Fallstricke. wenn f und G Funktionen kann Folgendes zu unerwartetem Verhalten führen:

z=max(f(),G());

In diesem Code sind die Funktionen nicht beide genau einmal ausgewertet (dann den höchsten Wert eingeben z vor Ort) wie man sich vorstellen kann. Jedoch, einer der Beiden Funktionen werden zweimal ausgeführt. Wenn diese Funktion nicht referenziell transparent (dh: mit Nebenwirkungen) kann dies unerwartete Folgen haben.

Makros können neue Syntax erstellen, aber auch beliebigen Text (der C-Compiler erzwingt gültiges C oder Kommentar). Ein Makro kann wie eine Funktion verwendet werden, aber es gibt Unterschiede. Zusätzlich zu dem oben genannten Problem hat ein Makro keine Speicheradresse damit ein Makro nicht mit a . an eine andere Funktion übergeben werden kann Funktionszeiger.

Bedingte Kompilierung

Mit dem C-Präprozessor ist es unter bestimmten Bedingungen auch möglich, Teile des Quellcodes zu kompilieren. Dadurch ist es möglich, verschiedene Versionen desselben Quellcodes in derselben Datei zu haben. Oft wird die bedingte Kompilierung verwendet, um die Kompilierung für eine bestimmte zu ändern Plattform oder Betriebssystem, um eine bestimmte Version zu kompilieren (eine Debug-Version enthält oft zusätzlichen Code im Vergleich zur endgültigen Version) oder um das mehrfache Einfügen einer bestimmten Header-Datei mit #include zu vermeiden.

In vielen Fällen wird die bedingte Kompilierung wie folgt verwendet:

#ifndef FOO_H#define FOO_H#einschließen"foo.h"#endif

Über ein Makro wird die Header-Datei foo.h nur eingefügt, wenn FOO_H noch nicht definiert ist. Die Konvention besteht darin, dieses Makro nach der eingefügten Header-Datei zu benennen. Wenn der Präprozessor zum ersten Mal auf den obigen Code stößt, wird der Inhalt von foo.h verwendet, während er beim zweiten Mal übersprungen wird, da FOO_H bereits definiert ist.

Bedingungen können auch auf komplexere Weise verwendet werden:

#ifdef x...#sonst...#endif

oder

#wenn x...#sonst...#endif

Diese Technik wird häufig in System-Header-Dateien verwendet, um bestimmte Eigenschaften zu überprüfen, deren Definition von der Plattform abhängen kann. Das GNU C-Bibliothek (glibc) verwendet diese Technik beispielsweise, um sicherzustellen, dass Unterschiede in Hardware und Betriebssystem mit denselben richtig behandelt werden Schnittstelle.

Heute wird diese Technik nicht mehr verwendet; die Kontrollen werden mit den üblichen durchgeführt wenn ... dann ... sonst ... und es bleibt dem Compiler überlassen, sicherzustellen, dass kein überflüssiger Code im fertigen Programm landet.