Is there something in the standard to back that up? Because I'm not convinced.Sven Schüle wrote: You can safely exclude (3) IMO since evaluation of one operand of == will be completed before evalulating the other one.
There's no sequence point to prevent it from evaluating some bits of the left side, then some bits of the right side, and I've always assumed that it could mix them for optimization reasons (e.g. the instructions might be best scheduled as two loads, followed by two pointer updates, followed by the comparison).
Edit: Here's another interesting thing, a description of warning options offered by gcc:
http://www.dis.com/gnu/gcc/Warning-Options.html
If you scroll down to -Wsequence-point, there is some interesting stuff:
Empasis mine. The updates to the two pointers before dereferencing them is fine, but if some other part of the expression somehow relies on the pointer value (e.g. the bizarro aliasing) then its going to have undefined behaviour because modifications to the "values of objects" (i.e. the pointer variable) could take effect at any time between the previous and next sequence point. You could think of this as saying, it will increment the register containing the pointer, and perform a load from the address that the register now points to... but when will the contents of the pointer register get written back to the memory address where that pointer lives? It could be any time before the next sequence point is reached (even with the most pessimistic of aliasing assumptions).The C standard defines the order in which expressions in a C program are evaluated in terms of sequence points, which represent a partial ordering between the execution of parts of the program: those executed before the sequence point, and those executed after it. These occur after the evaluation of a full expression (one which is not part of a larger expression), after the evaluation of the first operand of a &&, ||, ? : or , (comma) operator, before a function is called (but after the evaluation of its arguments and the expression denoting the called function), and in certain other places. Other than as expressed by the sequence point rules, the order of evaluation of subexpressions of an expression is not specified. All these rules describe only a partial order rather than a total order, since, for example, if two functions are called within one expression with no sequence point between them, the order in which the functions are called is not specified. However, the standards committee have ruled that function calls do not overlap.
It is not specified when between sequence points modifications to the values of objects take effect. Programs whose behavior depends on this have undefined behavior; the C standard specifies that “Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.”. If a program breaks these rules, the results on any particular implementation are entirely unpredictable.
Examples of code with undefined behavior are a = a++;, a[n] = b[n++] and a[i++] = i;. Some more complicated cases are not diagnosed by this option, and it may give an occasional false positive result, but in general it has been found fairly effective at detecting this sort of problem in programs.