Features of the mql5 language, subtleties and tricks - page 249

 
Dominik Egert #:

Probably because the compiler does unrole and reduces it to a single assignment line....

Then it's a compiler error.
Try using a random number instead of incrementing by 1.

Replacing it with MathRand, which logically is never called, makes a non-zero value. This further supports the hypothesis that zero is a compiler error.

 
fxsaber #:
Then it's a compiler error.

Replacing it with MathRand, which logically is never called, makes a non-zero value. This further supports the hypothesis that zero is a compiler error.

Maybe... Not sure about that. But only because you don't initialize MqlTick.

But I guess the compiler looks at it like this:

Function f2 evaluates to 0 in all cases in your code, so the for loop is with no effect, and therefore gets cut out and replaced with one single assignment.
 
Dominik Egert #:
The f2 function evaluates to 0 in all cases in your code, so the for loop has no effect, and so it is cut out and replaced by a single assignment.

Why?

 
fxsaber #:

Why?

Because f2 tmp is NOT zero, and therefore will return tick unmodified.

Compiler probably assumes you want MqlTick to be all zero, therefore it will evaluate to zero under all circumstances.

The assumption by the compiler MqlTick being zero is where the "bug" probably is, as far as this can be considered a bug, and not an oversight by the coder, which gets corrected by the compiler.
 
Dominik Egert #:
Because f2 tmp is NOT null, and so will return tick unchanged.
It doesn't. For example, swap the Bench1 and Bench2 calls.
void OnStart()
{  
  datetime Tmp = 0;

  BENCH(Bench2(Tmp))
  BENCH(Bench1(Tmp))
  
  Print(Tmp);  
}
 
Dominik Egert #:
How do you know it will be initialised? Won't it just be filled with values? Or is that what you mean by "initialised".

I don't know, I'm relying on the docs. It says that the structure must be filled. But if a value is not assigned to a field in the function being called, we get a UB when we get the value of that field later.

 
fxsaber #:

Tried it.


Result.

Frankly speaking, I don't understand why the second line gets zero when there is no initialisation.


This is UB behaviour. Since you return the value of the field, the compiler thinks you have initialised it, the only place where you do that is

Tick.time = 1;

Accordingly, your entire function is reduced by the optimiser to

datetime f2( datetime &Tmp )
{
 return 1;
}
 
fxsaber #:
It doesn't. For example, swap the Bench1 and Bench2 calls.
I still think the compiler reduces the for loop to one line...

Actually, maybe the compilers optimizer misses out on the optimization on the static variable, due to it coming from a different memory region, and therefore might assume, it is not local and could be changed externally, like a buffer by the terminal.

Or, optionally, the code is actually working as expected, but it is optimized into a register and so fast, we cannot measure it with micros.
 
Vladimir Simakov #:


This is the behaviour under UB. Since you return the value of the field, the compiler assumes you have initialised it, the only place you do that is

Consequently, your entire function is reduced by the optimiser to

Yes, that's exactly what happens.
If you put = rand() instead of 1, static loses.
 
Nikolai Semko #:
If you put = rand() instead of 1, static loses.

Parity.

Bench1(Tmp):5532 mcs.
Bench2(Tmp):5654 mcs.
Reason: