Особенности языка mql5, тонкости и приёмы работы - страница 152

 
Slava:

А он есть? Точно есть? По какому пути?

Как можно воспроизвести?

Поместить скрипт в Избранное Навигатора.

void OnStart() {}


Скомпилировать ошибочный вариант

void OnStart() {} 123


Перезагрузить Терминал и попробовать из Избранного выбрать редактирование скрипта.

 
Vladimir Simakov:

Разработчики. Пояснение нужно. Чему верить? Докам или реализации? Пока что undefined behavior получается.

@fxsaber, не советую до официальных пояснений юзать, вдруг возьмут и пофиксят.

Документация отстала, поправим

Я не рекомендую инициализировать статические переменные выражениями, если это возможно используйте константу.

Т.к. при использовании неконстантных выражений компилятором генерируется следующий код

//--- исходная функция
int func(int value)
  {
   static int myStaticVar=value;    
   
   myStaticVar += value;
   return(myStaticVar);
  }

//--- то, что будет сгенерировано 
bool __Implicit_myStaticVar_initialized=false;
int  __Implicit_myStaticVar=0;

//--- исходная функция
int func(int value)
  {
   if(!__Implicit_myStaticVar_initialized)
     {
      __Implicit_myStaticVar_initialized=true;
      __Implicit_myStaticVar=value;
     }

   __Implicit_myStaticVar += value;
   return(__Implicit_myStaticVar);
  }


Получается оверхед, на каждом вызове будет проверка флага __Implicit_myStaticVar_initialized

Для варианта с константой получится следующий код

//--- исходная функция
int func(int value)
  {
   static int myStaticVar=10;

   myStaticVar += value;
   return(myStaticVar);
  }

//--- то, что будет сгенерировано 
int  __Implicit_myStaticVar=10;

int func(int value)
  {
   __Implicit_myStaticVar += value;
   return(__Implicit_myStaticVar);
  }

Никакого оверхеда нет

 
Ilyas:

Спасибо, теперь понятно с оверхедом.

 
В кастомные символы можно запросто записывать не нормализованные значения цен. Ниже простая проверка.
bool IsNorm( const double Price )
{
  return(NormalizeDouble(Price, _Digits) == Price);
}

#define TOSTRING(A) #A + " = " + DoubleToString(A, 16) + " "
#define PRINT(A) Print(TOSTRING(A) + TOSTRING(NormalizeDouble(A, _Digits)))
#define ISNORM(A) if (!IsNorm(A)) PRINT(A);

void OnTick()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
  {
    ISNORM(Tick.bid)
    ISNORM(Tick.ask)
    ISNORM(Tick.last)
  }
}


Результат

2019.12.11 06:46:56.458 2019.10.09 23:59:00   Tick.last = 1.8151900000000002 NormalizeDouble(Tick.last,_Digits) = 1.8151900000000000 
2019.12.11 06:46:56.458 2019.10.09 23:59:11   Tick.bid = 1.8151100000000003 NormalizeDouble(Tick.bid,_Digits) = 1.8151100000000001 
2019.12.11 06:46:56.458 2019.10.09 23:59:11   Tick.ask = 1.8153800000000003 NormalizeDouble(Tick.ask,_Digits) = 1.8153800000000001 
2019.12.11 06:46:56.458 2019.10.09 23:59:17   Tick.bid = 1.8151200000000002 NormalizeDouble(Tick.bid,_Digits) = 1.8151199999999999 
2019.12.11 06:46:56.458 2019.10.09 23:59:17   Tick.ask = 1.8153800000000003 NormalizeDouble(Tick.ask,_Digits) = 1.8153800000000001 
 
Комментарии, не относящиеся к этой теме, были перенесены в "Вопросы от начинающих MQL5 MT5 MetaTrader 5".
 
RickD:
... Вопрос в другом. Возможно в MQL5 баг, нужно разобраться, а перенос в тему для начинающих никак не способствует скорому разбору ситуации.

Название темы прочтите пожалуйста.

 
Artyom Trishkin:

Название темы прочтите пожалуйста.

И в чем вы увидели противорчие? Описанная ситуация может быть как особенностью языка, так и багом. Это и требовалось выяснить.

 
RickD:

И в чем вы увидели противорчие? Описанная ситуация может быть как особенностью языка, так и багом. Это и требовалось выяснить.

Нет. Сначала выясняется баг это или особенность - потом постится именно, и исключительно особенность. Тема - только про особенности.

 

@Ilyas @Slava @Renat Fatkhullin

В mql есть поддержка не документированных ключевых слов для функций

__inline
__forceinline

Есть ли смысл их использовать?
Если да, то в каких случаях компилятор примет их?

 

В справке ArrayReverse:

Функция ArraySetAsSeries() физически не перемещает элементы массива, а только меняет направление индексации задом наперед для организации доступа к элементам как в таймсерии. Функция ArrayReverse() физически перемещает элементы массива таким образом, что массив "переворачивается".

Но этот код доказывает обратное: 

  MqlRates rt[];
  CopyRates(Symbol(), 0, 0, 5, rt);
  ArraySetAsSeries(rt, true);
  ArrayResize(rt, 6); // добавляет элемент в конец массива
  //ArraySetAsSeries(rt, true);
  for (int x = 0; x < ArraySize(rt); x++) {
      Print(rt[x].time);
  }
  Print("=================");
(EURUSD,H1)     2019.12.13 02:00:00
(EURUSD,H1)     2019.12.13 01:00:00
(EURUSD,H1)     2019.12.13 00:00:00
(EURUSD,H1)     2019.12.12 23:00:00
(EURUSD,H1)     2019.12.12 22:00:00
(EURUSD,H1)     1970.01.01 00:00:00 - последний элемент
(EURUSD,H1)     =================
  MqlRates rt[];
  CopyRates(Symbol(), 0, 0, 5, rt);
  //ArraySetAsSeries(rt, true);
  ArrayResize(rt, 6); // добавляет элемент в конец массива
  ArraySetAsSeries(rt, true);
  for (int x = 0; x < ArraySize(rt); x++) {
      Print(rt[x].time);
  }
  Print("=================");
(EURUSD,H1)     1970.01.01 00:09:19 - последний элемент
(EURUSD,H1)     2019.12.13 02:00:00
(EURUSD,H1)     2019.12.13 01:00:00
(EURUSD,H1)     2019.12.13 00:00:00
(EURUSD,H1)     2019.12.12 23:00:00
(EURUSD,H1)     2019.12.12 22:00:00
(EURUSD,H1)     =================
Причина обращения: