Предопределенные макроподстановки

Для облегчения отладки и получения информации о работе mql5-программы введены специальные константы-макросы, значения которых устанавливается в момент компиляции. Самый простой путь использования этих констант – вывод значений с помощью функции Print(), как показано в примере.

Константа

Описание

__CPU_ARCHITECTURE__

Имя архитектуры (набор команд), под которую собран файл EX5 при компиляции

__DATE__

Дата компиляции файла без времени (часы, минуты и секунды равны 0)

__DATETIME__

Дата и время компиляции файла

__LINE__

Номер строки в исходном коде, на которой расположен данный макрос

__FILE__

Имя текущего компилируемого файла

__PATH__

Абсолютный путь к текущему компилируемому файлу

__FUNCTION__

Имя функции, в теле которой расположен макрос

__FUNCSIG__

Сигнатура функции, в теле которой расположен макрос. Вывод в лог полного описания функции с типами параметров может пригодиться при идентификации перегруженных функций

__MQLBUILD__, __MQL5BUILD__

Номер билда компилятора

__COUNTER__

Компилятор для каждого встретившегося объявления __COUNTER__ подставляет по месту значение счетчика от 0 до N-1, где N – число использований в коде.  При перекомпиляции исходного кода без изменений порядок __COUNTER__ гарантируется.

Значение счетчика __COUNTER__ вычисляется следующим образом:

  • начальное значение счетчика равно 0,
  • после каждого использования счетчика его значение увеличивается на 1,
  • сначала компилятор разворачивает все макросы и шаблоны в исходный код по месту,
  • для каждой специализации шаблонной функции создается отдельный код,
  • для каждой специализации шаблонного класса/структуры создается отдельный код,
  • затем компилятор проходит по полученному исходному коду в установленном порядке и заменяет каждое встретившееся использование __COUNTER__ на текущее значение счетчика.

В примере ниже можно наглядно увидеть, как компилятор обрабатывает исходный код и заменяет встретившиеся __COUNTER__ на последовательно возрастающие значения.

__RANDOM__

Компилятор для каждого объявления __RANDOM__ подставляет в код случайное ulong-число.

Пример:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- пример вывода информации при инициализации советника
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
//--- установка интервала между событиями таймера
   EventSetTimer(5);
//---
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- пример вывода информации при деинициализации советника
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
 
//--- вывод информации при поступлении тика
   Print(" __MQLBUILD__ = ",__MQLBUILD__,"  __FILE__ = ",__FILE__);
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
   test1(__FUNCTION__);
   test2();
//---
  }
//+------------------------------------------------------------------+
//| test1                                                            |
//+------------------------------------------------------------------+
void test1(string par)
  {
//--- вывод информации внутри функции
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__," par=",par);
  }
//+------------------------------------------------------------------+
//| test2                                                            |
//+------------------------------------------------------------------+
void test2()
  {
//--- вывод информации внутри функции
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
  }
//+------------------------------------------------------------------+
//| OnTimer event handler                                            |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   Print(" __FUNCTION__ = ",__FUNCTION__,"  __LINE__ = ",__LINE__);
   test1(__FUNCTION__);
  }

 

Пример для изучения работы с макросом __COUNTER__

//--- создадим макрос для быстрого вывода в журнал выражения и его значения
#define print(exprPrint(#expr,"=",expr)
 
//--- определим пользовательский макрос MACRO_COUNTER через предопределенный макрос __COUNTER__
#define MACRO_COUNTER __COUNTER__
 
//--- задаем значение input переменной макросом __COUNTER__
input int InpVariable = __COUNTER__;
 
//--- задаем значение глобальной переменной макросом __COUNTER__ перед определением функций
int ExtVariable = __COUNTER__;
 
//+------------------------------------------------------------------+
//| функция возвращает значение __COUNTER__                          |
//+------------------------------------------------------------------+
int GlobalFunc(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| шаблонная функция возвращает значение __COUNTER__                |
//+------------------------------------------------------------------+
template<typename T>
int GlobalTemplateFunc(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| структура с методом, который возвращает __COUNTER__              |
//+------------------------------------------------------------------+
struct A
  {
   int               dummy;  // не используется
 
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| шаблонная структура с методом, который возвращает __COUNTER__    |
//+------------------------------------------------------------------+
template<typename T>
struct B
  {
   int               dummy;  // не используется
 
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| структура с шаблонным методом, который возвращает __COUNTER__    |
//+------------------------------------------------------------------+
struct C
  {
   int               dummy;  // не используется
 
   template<typename T>
   int               Method(void)
     {
      return(__COUNTER__);
     }
  };
//+------------------------------------------------------------------+
//| функция #2, которая возвращает значение __COUNTER__              |
//+------------------------------------------------------------------+
int GlobalFunc2(void)
  {
   return(__COUNTER__);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(void)
  {
// __COUNTER__ в макросе и переменных
   print(MACRO_COUNTER);
   print(InpVariable);
   print(ExtVariable);
 
//--- __COUNTER__ в функциях
   print(GlobalFunc());
   print(GlobalFunc());                // значение не меняется
   print(GlobalTemplateFunc<int>());
   print(GlobalTemplateFunc<int>());   // значение не меняется
   print(GlobalTemplateFunc<double>());// значение поменялось
   print(GlobalFunc2());
   print(GlobalFunc2());               // значение не меняется
 
// __COUNTER__ в структуре
   A a1a2;
   print(a1.Method());
   print(a2.Method());                 // значение не меняется
 
// __COUNTER__ в шаблонной структуре
   B<intb1b2;
   B<doubleb3;
   print(b1.Method());
   print(b2.Method());                 // значение не меняется
   print(b3.Method());                 // значение поменялось
 
// __COUNTER__ в структуре с шаблонной функцией
   C c1c2;
   print(c1.Method<int>());
   print(c1.Method<double>());         // значение поменялось
   print(c2.Method<int>());            // значение как при первом вызове c1.Method<int>()
 
//--- еще раз посмотрим __COUNTER__ в макросе и глобальной переменной
   print(MACRO_COUNTER);  // значение поменялось
   print(ExtGlobal2);
  }
//--- задаем значение глобальной переменной макросом __COUNTER__ после определений функций
int ExtGlobal2 = __COUNTER__;
//+------------------------------------------------------------------+
 
/* Результат
   __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
 
*/