Vorbestimmte Makrosubstitutionen

für die Erleichterung des ebugging und der Informationserhaltung über die Arbeit des mql5-Programms werden spezielle Konstanten-Makros eingeführt, deren Werte im Augenblick der Compilierung vorgegeben werden. Das einfachste Verfahren von Verwendung dieser Konstanten - Ausgabe der Werte mit der Funktion Print(), wie es im Beispiel gezeigt wird.

Konstante

Beschreibung

__CPU_ARCHITECTURE__

Name der Architektur (Befehlssatz), für den die EX5-Datei kompiliert wurde.

__DATE__

Datum der Kompilierung einer Date ohne die Uhrzeit (Stunden, Minuten und Sekunden sind 0)

__DATETIME__

Datum und Uhrzeit der Kompilierung einer Date

__LINE__

Nummer der Zeile im Ausgangskode, auf der sich der Makro befindet

__FILE__

Name der laufenden kompilierten Datei

__PATH__

Absoluter Pfad zu der laufenden kompilierten Datei

__FUNCTION__

Funktionsname, in deren Körper sich das Makro befindet  

__FUNCSIG__

Signatur der Funktion, in deren Körper befindet sich das Makro. Protokollierung der vollständige Beschreibung der Funktionen kann bei der Identifizierung von überladenen Funktionen nützlich sein

__MQLBUILD__, __MQL5BUILD__

Buildnummer des Compilers

__COUNTER__

Der Compiler ersetzt für jede angetroffene Deklaration von __COUNTER__ den Zählerwert von 0 bis N-1, wobei N eine Anzahl von Verwendungen im Code ist.  Der Befehl __COUNTER__ wird beim Neukompilieren des Quellcodes ohne Änderungen garantiert.

Der Wert von __COUNTER__ wird auf folgende Weise berechnet:

  • der anfängliche Wert des Zählers ist 0,
  • nach jeder Verwendung des Zählers wird sein Wert um 1 erhöht,
  • zunächst expandiert der Compiler alle Makros und Templates lokal in Quellcode,
  • für jede spezielle Funktion eines Templates wird ein eigener Code erzeugt,
  • für jede spezielle Klasse/Struktur eines Templates wird ein separater Code erzeugt,
  • anschließend durchläuft der Compiler den erhaltenen Quellcode in dem definierten Auftrag und ersetzt jede erkannte Verwendung von __COUNTER__ durch den aktuellen Zählerwert.

Das Beispiel unten zeigt, wie der Compiler den Quellcode behandelt und alle Instanzen von __COUNTER__, auf die er trifft, durch sequentiell steigende Werte ersetzt.

__RANDOM__

Der Compiler fügt für jede Deklaration von __RANDOM__ einen zufälligen ulong-Wert ein.

Beispiel:

#property copyright "Copyright © 2009, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- Beispiel der Informationsausgabe bei der Ratgeberinitialisierung 
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
//--- Einstellung des Intervals zwischen Ereignisse des Timers 
   EventSetTimer(5);
//---
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Beispiel der Inforamtionsausgabe bei der Deinitialisierung des Ratgebers  
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
 
//--- Ausgabe der Information beim Tickaufnahme 
   Print(" __MQLBUILD__ = ",__MQLBUILD__,"  __FILE__ = ",__FILE__);
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
   test1(__FUNCTION__);
   test2();
//---
  }
//+------------------------------------------------------------------+
//| test1                                                            |
//+------------------------------------------------------------------+
void test1(string par)
  {
//--- Informationsausgabe innerhalb der Funktion 
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__," par=",par);
 ;}
//+------------------------------------------------------------------+
//| test2                                                            |
//+------------------------------------------------------------------+
void test2()
  {
//--- Informationsausgabe innerhalb der Funktion 
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
  }
//+------------------------------------------------------------------+
//| OnTimer event handler                                            |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
   test1(__FUNCTION__);
  }

 

Das Beispiel zur Verdeutlichung der Arbeit mit dem Makro __COUNTER__

//--- Erstellen eines Makro für eine schnelle Anzeige des Ausdrucks und seines Wertes im Journal
#define print(exprPrint(#expr,"=",expr)
 
//--- Definieren des nutzerdefinierten Makros MACRO_COUNTER mit Hilfe des vordefinierten Makros __COUNTER__
#define MACRO_COUNTER __COUNTER__
 
//--- den Eingabewerte der Variablen mit dem Makro __COUNTER__ setzen
input int InpVariable = __COUNTER__;
 
//--- Zuweisen des Wertes einer globalen Variablen mit dem Makro __COUNTER__ vor dem Deklarieren der Funktion
int ExtVariable = __COUNTER__;
 
//+------------------------------------------------------------------+
//| Die Funktion gibt den Wert von __COUNTER__ zurück                |
//+------------------------------------------------------------------+
int GlobalFunc(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| Das Funktionstemplate gibt den Wert von __COUNTER__ zurück       |
//+------------------------------------------------------------------+
template<typename T>
int GlobalTemplateFunc(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| Die Struktur mit der Methode, die __COUNTER__ zurückgibt         |
//+------------------------------------------------------------------+
struct A
  {
   int               dummy;  // nicht verwendet
 
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| Das Strukturtemplate mit der Methode, die __COUNTER__ zurückgibt |
//+------------------------------------------------------------------+
template<typename T>
struct B
  {
   int               dummy;  // nicht verwendet
 
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| Die Struktur mit der Templatemethode, die __COUNTER__ zurückgibt |
//+------------------------------------------------------------------+
struct C
  {
   int               dummy;  // nicht verwendet
 
   template<typename T>
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| die Funktion #2, die den Wert __COUNTER__ zurückgibt             |
//+------------------------------------------------------------------+
int GlobalFunc2(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| Skript Programm Start Funktion                                   |
//+------------------------------------------------------------------+
void OnStart(void)
  {
// __COUNTER__ im Makro und den Variablen
   print(MACRO_COUNTER);
   print(InpVariable);
   print(ExtVariable);
 
//--- __COUNTER__ in den Funktionen
   print(GlobalFunc());
   print(GlobalFunc());                // der Wert hat sich nicht geändert
   print(GlobalTemplateFunc<int>());
   print(GlobalTemplateFunc<int>());   // der Wert hat sich nicht geändert
   print(GlobalTemplateFunc<double>());// der Wert hat sich nicht geändert
   print(GlobalFunc2());
   print(GlobalFunc2());               // der Wert hat sich nicht geändert
 
// __COUNTER__ in der Struktur
   A a1a2;
   print(a1.Method());
   print(a2.Method());                 // der Wert hat sich nicht geändert
 
// __COUNTER__ im Strukturtemplate
   B<intb1b2;
   B<doubleb3;
   print(b1.Method());
   print(b2.Method());                 // der Wert hat sich nicht geändert
   print(b3.Method());                 // der Wert hat sich geändert
 
// __COUNTER__ in der Struktur mit einer Templatefunktion
   C c1c2;
   print(c1.Method<int>());
   print(c1.Method<double>());         // der Wert hat sich geändert
   print(c2.Method<int>());            // der gleiche Wert wie beim ersten Aufruf von c1.Method<int>()
 
//--- Sehen wir uns noch einmal __COUNTER__ im Makro und die globale Variable an
   print(MACRO_COUNTER);  // der Wert hat sich geändert
   print(ExtGlobal2);
  }
//--- Wir setzen den Wert der globalen Variablen mit dem Makro __COUNTER__, nachdem wir die Funktionen definiert haben
int ExtGlobal2 = __COUNTER__;
//+------------------------------------------------------------------+
 
/* Ergebnis
   __COUNTER__=3
   InpVariable=0
   ExtVariable=1
   GlobalFunc()=5
   GlobalFunc()=5
   GlobalTemplateFunc<int>()=8
   GlobalTemplateFunc<int>()=8
   GlobalTemplateFunc<double>()=9
   GlobalFunc2()=7
   GlobalFunc2()=7
   a1.Method()=6
   a2.Method()=6
   b1.Method()=10
   b2.Method()=10
   b3.Method()=11
   c1.Method<int>()=12
   c1.Method<double>()=13
   c2.Method<int>()=12
   __COUNTER__=4
   ExtGlobal2=2
 
*/