Objective-C-Präprozessoren
Das Objective-C Preprocessorist nicht Teil des Compilers, sondern ein separater Schritt im Kompilierungsprozess. Vereinfacht ausgedrückt ist ein Objective-C-Präprozessor nur ein Textersetzungswerkzeug und weist den Compiler an, vor der eigentlichen Kompilierung die erforderliche Vorverarbeitung durchzuführen. Wir werden den Objective-C-Präprozessor als OCPP bezeichnen.
Alle Präprozessorbefehle beginnen mit einem Pfund-Symbol (#). Es muss das erste nicht leere Zeichen sein, und aus Gründen der Lesbarkeit sollte eine Präprozessoranweisung in der ersten Spalte beginnen. Der folgende Abschnitt listet alle wichtigen Präprozessoranweisungen auf -
Sr.Nr. | Richtlinie & Beschreibung |
---|---|
1 | #define Ersetzt ein Präprozessor-Makro |
2 | #include Fügt einen bestimmten Header aus einer anderen Datei ein |
3 | #undef Undefiniert ein Präprozessor-Makro |
4 | #ifdef Gibt true zurück, wenn dieses Makro definiert ist |
5 | #ifndef Gibt true zurück, wenn dieses Makro nicht definiert ist |
6 | #if Testet, ob eine Kompilierungszeitbedingung erfüllt ist |
7 | #else Die Alternative für #if |
8 | #elif #else ein #if in einer Anweisung |
9 | #endif Beendet den Präprozessor unter bestimmten Bedingungen |
10 | #error Druckt eine Fehlermeldung auf stderr |
11 | #pragma Gibt spezielle Befehle mit einer standardisierten Methode an den Compiler aus |
Präprozessor-Beispiele
Analysieren Sie die folgenden Beispiele, um verschiedene Richtlinien zu verstehen.
#define MAX_ARRAY_LENGTH 20
Diese Anweisung weist das OCPP an, Instanzen von MAX_ARRAY_LENGTH durch 20 zu ersetzen. Verwenden Sie #define für Konstanten, um die Lesbarkeit zu verbessern .
#import <Foundation/Foundation.h>
#include "myheader.h"
Diese Anweisungen weisen die OCPP an, die Stiftung.h von zu erhalten Foundation Frameworkund fügen Sie den Text zur aktuellen Quelldatei hinzu. Die nächste Zeile weist OCPP an, abzurufenmyheader.h aus dem lokalen Verzeichnis und fügen Sie den Inhalt zur aktuellen Quelldatei hinzu.
#undef FILE_SIZE
#define FILE_SIZE 42
Dies weist das OCPP an, die vorhandene FILE_SIZE aufzuheben und als 42 zu definieren.
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
Dies weist das OCPP an, MESSAGE nur zu definieren, wenn MESSAGE noch nicht definiert ist.
#ifdef DEBUG
/* Your debugging statements here */
#endif
Dies weist das OCPP an, den Prozess mit den beiliegenden Anweisungen durchzuführen, wenn DEBUG definiert ist. Dies ist nützlich, wenn Sie das Flag -DDEBUG zum Zeitpunkt der Kompilierung an den gcc-Compiler übergeben. Dadurch wird DEBUG definiert, sodass Sie das Debuggen während der Kompilierung im laufenden Betrieb ein- und ausschalten können.
Vordefinierte Makros
ANSI C definiert eine Reihe von Makros. Obwohl jedes für Ihre Verwendung in der Programmierung verfügbar ist, sollten die vordefinierten Makros nicht direkt geändert werden.
Sr.Nr. | Makro & Beschreibung |
---|---|
1 | __DATE__ Das aktuelle Datum als Zeichenliteral im Format "MMM TT JJJJ" |
2 | __TIME__ Die aktuelle Zeit als Zeichenliteral im Format "HH: MM: SS" |
3 | __FILE__ Dieser enthält den aktuellen Dateinamen als Zeichenfolgenliteral. |
4 | __LINE__ Diese enthält die aktuelle Zeilennummer als Dezimalkonstante. |
5 | __STDC__ Definiert als 1, wenn der Compiler dem ANSI-Standard entspricht. |
Versuchen wir das folgende Beispiel:
#import <Foundation/Foundation.h>
int main() {
NSLog(@"File :%s\n", __FILE__ );
NSLog(@"Date :%s\n", __DATE__ );
NSLog(@"Time :%s\n", __TIME__ );
NSLog(@"Line :%d\n", __LINE__ );
NSLog(@"ANSI :%d\n", __STDC__ );
return 0;
}
Wenn der obige Code in einer Datei main.m wird kompiliert und ausgeführt, ergibt sich folgendes Ergebnis:
2013-09-14 04:46:14.859 demo[20683] File :main.m
2013-09-14 04:46:14.859 demo[20683] Date :Sep 14 2013
2013-09-14 04:46:14.859 demo[20683] Time :04:46:14
2013-09-14 04:46:14.859 demo[20683] Line :8
2013-09-14 04:46:14.859 demo[20683] ANSI :1
Präprozessor-Operatoren
Der Objective-C-Präprozessor bietet folgende Operatoren, die Sie beim Erstellen von Makros unterstützen:
Makro-Fortsetzung (\)
Ein Makro muss normalerweise in einer einzelnen Zeile enthalten sein. Der Makro-Fortsetzungsoperator wird verwendet, um ein Makro fortzusetzen, das für eine einzelne Zeile zu lang ist. Zum Beispiel -
#define message_for(a, b) \
NSLog(@#a " and " #b ": We love you!\n")
Stringize (#)
Der Stringize- oder Zahlenzeichenoperator ('#') konvertiert bei Verwendung innerhalb einer Makrodefinition einen Makroparameter in eine String-Konstante. Dieser Operator darf nur in einem Makro verwendet werden, für das ein Argument oder eine Parameterliste angegeben ist. Zum Beispiel -
#import <Foundation/Foundation.h>
#define message_for(a, b) \
NSLog(@#a " and " #b ": We love you!\n")
int main(void) {
message_for(Carole, Debra);
return 0;
}
Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:
2013-09-14 05:46:14.859 demo[20683] Carole and Debra: We love you!
Token einfügen (##)
Der Token-Pasting-Operator (##) in einer Makrodefinition kombiniert zwei Argumente. Damit können zwei separate Token in der Makrodefinition zu einem einzigen Token zusammengefügt werden. Zum Beispiel -
#import <Foundation/Foundation.h>
#define tokenpaster(n) NSLog (@"token" #n " = %d", token##n)
int main(void) {
int token34 = 40;
tokenpaster(34);
return 0;
}
Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:
2013-09-14 05:48:14.859 demo[20683] token34 = 40
Wie es passiert ist, denn dieses Beispiel führt zu der folgenden tatsächlichen Ausgabe vom Präprozessor -
NSLog (@"token34 = %d", token34);
Dieses Beispiel zeigt die Verkettung von Token ## n zu Token34, und hier haben wir beide verwendet stringize und token-pasting.
Der definierte () Operator
Der Präprozessor definedDer Operator wird in konstanten Ausdrücken verwendet, um zu bestimmen, ob ein Bezeichner mit #define definiert ist. Wenn der angegebene Bezeichner definiert ist, ist der Wert wahr (ungleich Null). Wenn das Symbol nicht definiert ist, ist der Wert falsch (Null). Der definierte Operator wird wie folgt angegeben:
#import <Foundation/Foundation.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void) {
NSLog(@"Here is the message: %s\n", MESSAGE);
return 0;
}
Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:
2013-09-14 05:48:19.859 demo[20683] Here is the message: You wish!
Parametrisierte Makros
Eine der leistungsstarken Funktionen des OCPP ist die Möglichkeit, Funktionen mithilfe parametrisierter Makros zu simulieren. Zum Beispiel könnten wir einen Code haben, um eine Zahl wie folgt zu quadrieren:
int square(int x) {
return x * x;
}
Wir können den obigen Code mit einem Makro wie folgt umschreiben:
#define square(x) ((x) * (x))
Makros mit Argumenten müssen mit dem definiert werden #defineRichtlinie, bevor sie verwendet werden können. Die Argumentliste ist in Klammern eingeschlossen und muss unmittelbar auf den Makronamen folgen. Zwischen dem Makronamen und der offenen Klammer sind keine Leerzeichen zulässig. Zum Beispiel -
#import <Foundation/Foundation.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void) {
NSLog(@"Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:
2013-09-14 05:52:15.859 demo[20683] Max between 20 and 10 is 20