Macro substituciones predefinidas

Para facilitar la depuración y obtener la información sobre el funcionamiento de un programa mql5 están previstas las constantes-macros especiales predefinidas, cuyos valores se establecen en el momento de compilación. La manera más fácil de usarlas consiste en la devolución de sus valores mediante la función Print(), como se muestra en el ejemplo de abajo.

Constante

Descripción

__CPU_ARCHITECTURE__

Nombre de la arquitectura (conjunto de comandos) con la que se ha creado el archivo EX5 al realizar la compilación

__DATE__

Fecha de compilación del archivo sin hora (horas, minutos y segundos son iguales a 0)

__DATETIME__

Fecha y hora de compilación del archivo

__LINE__

Número de cadena en el código fuente, en la que se ubica esta macro

__FILE__

Nombre del archivo corriente compilado

__PATH__

Ruta absoluta hacia el archivo actual a compilar

__FUNCTION__

Nombre de la función, en cuyo cuerpo está ubicado la macro

__FUNCSIG__

Signatura de la función en cuyo cuerpo se encuentra la macro. El mostrar en el log la descripción completa de la función con tipos de parámetros puede ser útil durante la identificación de las funciones sobrecargadas

__MQLBUILD__, __MQL5BUILD__

Número build del compilador

__COUNTER__

Para cada declaración __COUNTER__ encontrada, el compilador cambia en su lugar el valor del contador de 0 a N-1, donde N es el número de usos en el código.  Al recompilar el código fuente sin cambios, el orden __COUNTER__ está garantizado.

El valor del contador __COUNTER__ se calcula de la forma siguiente:

  • el valor inicial del contador es 0,
  • después de cada uso del contador, su valor aumenta en 1,
  • primero, el compilador expande en su sitio todas las macros y plantillas en el código fuente,
  • para cada especialización de la función de plantilla, se genera un código aparte,
  • para cada especialización de la clase/estructura de plantilla, se genera un código aparte,
  • a continuación, el compilador recorre el código fuente obtenido en el orden establecido y sustituye cada uso de __COUNTER__ encontrado por el valor actual del contador.

En el ejemplo de abajo, podemos ver con claridad cómo el compilador procesa el código fuente y va sustituyendo __COUNTER__ (a medida que encuentra dicho elemento) por valores en aumento secuencial.

__RANDOM__

Para cada declaración __RANDOM__, el compilador coloca en el código un número ulong aleatorio.

Ejemplo:

#property copyright "Copyright © 2009, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- ejemplo de output de información durante la inicialización del Asesor Experto
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
//--- definición de intervalos entre los eventos de temporizador
   EventSetTimer(5);
//---
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- ejemplo de output de información durante la deinicialización del Asesor Experto
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
 
//--- output de información durante la llegada de del tick
   Print(" __MQLBUILD__ = ",__MQLBUILD__,"  __FILE__ = ",__FILE__);
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
   test1(__FUNCTION__);
   test2();
//---
  }
//+------------------------------------------------------------------+
//| test1                                                            |
//+------------------------------------------------------------------+
void test1(string par)
  {
//--- output de información dentro de la función
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__," par=",par);
  }
//+------------------------------------------------------------------+
//| test2                                                            |
//+------------------------------------------------------------------+
void test2()
  {
//--- output de información dentro de la función
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
  }
//+------------------------------------------------------------------+
//| OnTimer event handler                                            |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
   test1(__FUNCTION__);
  }

 

Exemplo para aprender a trabalhar com uma macro __COUNTER__

//--- criamos uma macro para impressão rápida da expressão e seu valor no log
#define print(exprPrint(#expr,"=",expr)
 
//--- definimos uma macro customizada MACRO_COUNTER por meio da macro predefinida __COUNTER__
#define MACRO_COUNTER __COUNTER__
 
//--- definimos o valor da variável input com a macro __COUNTER__
input int InpVariable = __COUNTER__;
 
//--- definimos o valor da variável global com a macro __COUNTER__ antes de definir as funções
int ExtVariable = __COUNTER__;
 
//+------------------------------------------------------------------+
//| a função retorna o valor __COUNTER__                             |
//+------------------------------------------------------------------+
int GlobalFunc(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| função de modelo retorna valor __COUNTER__                       |
//+------------------------------------------------------------------+
template<typename T>
int GlobalTemplateFunc(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| estrutura com um método que retorna __COUNTER__                  |
//+------------------------------------------------------------------+
struct A
  {
   int               dummy;  // não é usado
 
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| estrutura baseada em modelo com um método que retorna __COUNTER__|
//+------------------------------------------------------------------+
template<typename T>
struct B
  {
   int               dummy;  // não é usado
 
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| estrutura com um método baseado em modelo que retorna __COUNTER__|
//+------------------------------------------------------------------+
struct C
  {
   int               dummy;  // não é usado
 
   template<typename T>
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| função #2, que retorna o valor __COUNTER__                       |
//+------------------------------------------------------------------+
int GlobalFunc2(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(void)
  {
// __COUNTER__ em macros e variáveis
   print(MACRO_COUNTER);
   print(InpVariable);
   print(ExtVariable);
 
/--- __COUNTER__ em funções
   print(GlobalFunc());
   print(GlobalFunc());                // o valor não muda
   print(GlobalTemplateFunc<int>());
   print(GlobalTemplateFunc<int>());   // o valor não muda
   print(GlobalTemplateFunc<double>());// o valor mudou
   print(GlobalFunc2());
   print(GlobalFunc2());               // o valor não muda
 
// __COUNTER__ na estrutura
   A a1a2;
   print(a1.Method());
   print(a2.Method());                 // o valor não muda
 
// __COUNTER__ na estrutura baseada em modelo
   B<intb1b2;
   B<doubleb3;
   print(b1.Method());
   print(b2.Method());                 // o valor não muda
   print(b3.Method());                 // o valor mudou
 
// __COUNTER__ em uma estrutura com uma função baseada em modelo
   C c1c2;
   print(c1.Method<int>());
   print(c1.Method<double>());         // o valor mudou
   print(c2.Method<int>());            // valor como ao chamar c1.Method<int>() pela primeira vez
 
//--- mais uma vez, olhamos para __COUNTER__ na macro e na variável global
   print(MACRO_COUNTER);  // o valor mudou
   print(ExtGlobal2);
  }
//--- definimos o valor da variável global com a macro __COUNTER__ após as definições da função
int ExtGlobal2 = __COUNTER__;
//+------------------------------------------------------------------+
 
/* Resultado
   __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
 
*/