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

 
fxsaber #:

Я попробовал.


Результат.

Честно говоря, я не понимаю, почему при отсутствии инициализации вторая строка становится нулевой.

Возможно, потому что компилятор делает unrole и сокращает ее до одной строки присваивания...

Попробуйте использовать случайное число вместо инкремента на 1.
 
Dominik Egert #:

Возможно, потому что компилятор делает unrole и сокращает ее до одной строки присваивания...

Тогда это ошибка компилятора.
Попробуйте использовать случайное число вместо инкремента на 1.

Замена на MathRand, который по логике никогда не вызывается, делает ненулевое значение. Это еще больше убеждает в верности гипотезы, что ноль - ошибка компилятора.

 
fxsaber #:
Тогда это ошибка компилятора.

Замена его на MathRand, который, по логике, никогда не вызывается, дает ненулевое значение. Это еще больше подтверждает гипотезу о том, что ноль - это ошибка компилятора.

Возможно... Не уверен в этом. Но только потому, что вы не инициализируете MqlTick.

Но я полагаю, что компилятор смотрит на это так:

Функция f2 оценивается в 0 во всех случаях в вашем коде, поэтому цикл for не имеет никакого эффекта, и поэтому он вырезается и заменяется одним единственным присваиванием.
 
Dominik Egert #:
Функция f2 оценивается в 0 во всех случаях в вашем коде, поэтому цикл for не имеет никакого эффекта, и поэтому он вырезается и заменяется одним единственным присваиванием.

Почему?

 
fxsaber #:

Почему?

Потому что f2 tmp НЕ является нулем, и поэтому вернет tick без изменений.

Вероятно, компилятор предполагает, что вы хотите, чтобы MqlTick был равен нулю, поэтому он будет оценивать его как нулевой при любых обстоятельствах.

В предположении компилятора, что MqlTick равен нулю, и кроется "ошибка", насколько это можно считать ошибкой, а не недосмотром кодера, который исправляется компилятором.
 
Dominik Egert #:
Потому что f2 tmp НЕ является нулем, и поэтому вернет tick без изменений.
Это не так. Например, поменяйте местами вызовы Bench1 и Bench2.
void OnStart()
{  
  datetime Tmp = 0;

  BENCH(Bench2(Tmp))
  BENCH(Bench1(Tmp))
  
  Print(Tmp);  
}
 
Dominik Egert #:
Откуда вы знаете, что она будет инициализирована? Разве она не будет просто заполнена значениями? Или вы подразумеваете это под словом "инициализируется".

А я не знаю, я полагаюсь на доки. Там сказано, что структура должна быть заполнена. А вот если какому-либо полю, в вызываемой функции значение не будет присвоено, то при получении значения этого поля в дальнейшем, получаем UB.

 
fxsaber #:

Попробовал.


Результат.

Честно говоря, не понимаю, почему во второй строке получается ноль при отсутствии инициализации.


Это поведение при UB. Так как ты возвращаешь значение поля, то компилятор считает, что ты его инициализировал, единственное место, где ты это делаешь - это  

Tick.time = 1;

Соответственно, вся твоя функция сводится оптимизатором к 

datetime f2( datetime &Tmp )
{
 return 1;
}
 
fxsaber #:
Это не так. Например, поменяйте местами вызовы Bench1 и Bench2.
Я все еще думаю, что компилятор сокращает цикл for до одной строки...

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

Или, как вариант, код действительно работает так, как ожидалось, но он оптимизирован в регистр и настолько быстр, что мы не можем измерить его микронами.
 
Vladimir Simakov #:


Это поведение при UB. Так как ты возвращаешь значение поля, то компилятор считает, что ты его инициализировал, единственное место, где ты это делаешь - это  

Соответственно, вся твоя функция сводится оптимизатором к 

Да, именно так и происходит.
Если поставить = rand() вместо 1, то  static  проигрывает.