The code flow is as follows:
The if statement calls the f() method first time, x becomes 1, ok = !ok evaluates to ok = !true, f() returns false. Since the first argument passed to || is false, the compiler tries to evaluate the second argument, which is f() | f() (| is the bitwise inclusive or operator).
The | operator calls the f() method twice, x incremented twice will become 3, the second f() method call will return true and the third call will return false.
Consequently if (f()||f()|f()) evaluates to if ( false || true | false) . true | false = true. false || true = true. x = 3.
for (int i=0; i<3; i++)