It is equal because this is C. As the other answer says, the result of this operation is undefined because you violate C rules -- which means that you cannot guarantee the same answer when switching compilers (although all compilers may be implemented similar, which doesn't make it a guarantee). The fact that C allows you to shoot yourself in the foot does not mean that it is good practice to do so.
Now, why does it work?
Conjecture #1:
i
may be stored in a register, say r1
, and the compiler may be compiling this entire comparison into one single CMP instruction, with an autoincrement addressing mode. Say it is CMP ++r1, r1
or CMP r1, ++r1
, then depending on the actual CPU, both may return a true compare.
Conjecture #2:
The compiler may be compiling the compare into:
inc r1 // increment r1
CMP r1, r1 // compare with itself
Conjecture #3:
The compiler may be optimizing to always put a simple variable access to the right hand side. It is allowed to do that because the order of execution in a ==
operator is undefined and the compiler can rearrange things as it likes.