in reply to Re^24: Why is the execution order of subexpressions undefined?
in thread Why is the execution order of subexpressions undefined?
BrowserUk, you're confusing most of us, I think. Defined EO implies serialisation, undefined EO implies parallelisable, and you keep stating it backwards.
Yes, separate statements means serialise. The semicolon is a "sequence" point (as per the ANSI C definition) which means that all effects and side effects must be resolved from the expression previous to the sequence point before beginning resolution of the expression following that sequence point. There are other sequence points other than the semicolon (&&, ||, ?:, and maybe even ()). But the bottom line is that anything happening between sequence points is undefined, but from one sequence point to the next is always in code order.
It's the very fact that having the EO left as undefined that the compiler says, "I trust the developer that there are no interdependancies, because I haven't told the developer how I'm going to resolve them." If you don't know that func1 is called before, after, or at the same time as func2, then you shouldn't be putting them in the same expression (between sequence points) if they have interdependancies.
However, if you know that func1 is called prior to func2, then you also know that func2 is about to be called with a value of $var that is 1 more than func1 was called with, and you may depend on this. If you depend on this behaviour, the compiler cannot parallelise func1 and func2 because you expect the op to be a sequence point where all side effects of func1 are resolved prior to func2 being called.
You just simply have the effects of defined EO backwards.
$a = 1; $x = $a++ + ++$a;
Let's say we did define EO as left-to-right. That means that $a++ would evaluate prior to ++$a. Thus, the compiler must finish evaluating (and storing) $a++ completely prior to beginning evaluation of ++$a. That means that the compiler must take $a (1), put it in the register, and increment the remote memory, then take $a again (now 2), increment it (now 3) and put it back into remote memory, and add the current value to the former value, and get $x = 4, $a = 3. That is the definition of serial processing.
If, however, we leave the EO undefined, the compiler could start evaluating $a++ (e.g., load the number 1 into a register), then start evaluating ++$a (e.g., load the number 1 again into another register), continue evaluating ++$a (add one in the register, now 2), go back to evaluating $a++ (increment the value in RAM, not the register, to 2), go back to evaluating ++$a (store the new value 2 in RAM), and then finally add the two (registers) together. This would leave $a = 2, and $x = 3. Note how the compiler did evaluate this in parallel. The programmer said that there were no interdependancies, but was incorrect in that statement, and the undefined nature of the outcome is based solely on this ability of the compiler to parallelise the activity.
|
|---|