Makrosubstitution (#define, #undef)

Der Compiler verwendet Direktiven des Präprozessors für eine vorbereitende Verarbeitung eines Quellcodes vor der Kompilierung. Die Direktive beginnt immer mit dem Zeichen # (Doppelkreuz), deswegen verbietet der Compiler, dieses Zeichen in den Namen von Variablen, Funktionen usw. zu verwenden.

Jede Direktive wird in einem separaten Eintrag beschrieben und ist bis zum Zeilenumbruch gültig. In einem Eintrag können Sie nur eine Direktive verwenden. Wenn der Eintrag der Direktive zu groß ist, kann er mithilfe des Zeichens '\' in mehrere Zeilen aufgeteilt werden. In diesem Fall gilt die nächste Zeile als eine Fortsetzung des Eintrags dieser Direktive.

Befehlende Anweisung #define kann verwendet werden, um mnemonische Namen den zuzuordnen. Es gibt zwei Formen:

#define identifier expression                   // parameterfreie Form
#define identifier(par1,... par8) expression    // parametrische Form

Befehlsanweisung #define ersetzt expression anstatt aller folgenden gefundenen Eintragungen von  identifier im Ausgangstext. identifier wird erst dann ersetzt, wenn er einzelner token darstellt. identifier wird nicht ersetzt, wenn er ein Teil des Kommentars, der Zeile oder eines anderen laengeren Identifikators ist.

für den Identifikator der Konstante gelten dieselbe Regeln, wie für die Konstantennamen. Der wert kann jeder Art sein:

#define ABC               100
#define PI                3.14
#define COMPANY_NAME      "MetaQuotes Software Corp."
...
void ShowCopyright()
  {
   Print("Copyright  2001-2009, ",COMPANY_NAME);
   Print("https://www.metaquotes.net");
  }

expression kann aus mehreren tokens bestehen, wie Schluesselwoerter, Konstanten, Konstant- und Nichtkonstantausdrücke. expression beendetmit dem Zeilenende und kann nicht auf die naechste Zeile ubertragen werden.

Beispiel:

#define TWO        2
#define THREE      3
#define INCOMPLETE TWO+THREE
#define COMPLETE  (TWO+THREE)
void OnStart()
  {
   Print("2 + 3*2 = ",INCOMPLETE*2);
   Print("(2 + 3)*2 = ",COMPLETE*2);
  }
/* Ergebnis
   2+3*2 = 8
   (2+3)*2 = 10
*/

 

Parametrische Form #define

Mit der parametrischen Form, werden alle folgenden gefunden Einträge von identifier werden durch expression auf der Grundlage der aktuellen Parameter ersetzt werden. Zum Beispiel,

 // Beispiel mit zwei Parameter a und b
#define A 2+3
#define B 5-1
#define MUL(a, b) ((a)*(b))
 
double c=MUL(A,B);
Print("c=",c);
/*
Expression double c=MUL(A,B);
ist gleichbedeutend mit double c=((2+3)*(5-1));
*/
// Ergebnis
// c=20

Achten Sie darauf, dass Parameter in Klammern eingeschlossen sind, wenn Sie den Parameter in expression verwenden, da dies nicht-offensichtlichen Fehlern, die schwer zu finden sind, vermeidet. Wenn wir den Code neu schreiben, ohne die Klammern, wird das Ergebnis anders sein:

 // Beispiel mit zwei Parameter a und b
#define A 2+3
#define B 5-1
#define MUL(a, b) a*b
 
double c=MUL(A,B);
Print("c=",c);
/*
Expression double c=MUL(A,B);
ist gleichbedeutend mit double c=2+3*5-1;
*/
// Ergebnis
// c=16

Bei Verwendung der parametrischen Form sind maximal 8 Parameter erlaubt.

 // richtige parametrische Form
#define LOG(text)  Print(__FILE__,"(",__LINE__,") :",text)   // ein Parameter - 'text'
 
 // falsche parametrische Form         
#define WRONG_DEF(p1, p2, p3, p4, p5, p6, p7, p8, p9)   p1+p2+p3+p4 // mehr als 8 Parameter p1 bis p9

Direktive #undef

Direktive #undef annulliert das früher definierten Makro.

Beispiel:

#define MACRO
 
void func1()
  {
#ifdef MACRO
   Print("MACRO is defined in ",__FUNCTION__);   
#else
   Print("MACRO is not defined in ",__FUNCTION__);
#endif
  }
 
#undef MACRO
 
void func2()
  {
#ifdef MACRO
   Print("MACRO is defined in ",__FUNCTION__);
#else
   Print("MACRO is not defined in ",__FUNCTION__);
#endif
  }
 
void OnStart()
  {
   func1();
   func2();
  }
 
/* Ergebnis:
 MACRO is defined in func1
 MACRO is not defined in func2
*/

Sehen Sie auch

Identifikatoren, Symbolkonstanten