If I write:
x = y & foo();
foo will always get called, but is that really defined? In theory, barring the standard saying otherwise, if
0, a runtime optimization could skip the call in the absense of something saying that's not allowed. (And similarly with
|, you could ignore the right-hand operand if the left-hand operand were already all-bits-on. For that matter, even
x = y * foo(); could be short-circuited if
Not knowing the specification well (and I don't), it's tricky to prove a negative like that. I can contrast the sections on
& (6.5.10 in C99) and
&& (6.5.13 in C99). In the latter, it's perfectly clear:
Unlike the bitwise binary
&&operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares equal to
0, the second operand is not evaluated.
...but 6.5.10 doesn't specifically state the negative version of that.
It seems reasonable to me to take the fact that 6.5.10 doesn't define a sequence point to mean that
foo will always get called and an implementation that didn't call it would be non-standard. Am I right about that?
It seems reasonable to me to take the fact that 6.5.10 doesn't define a sequence point to mean that foo will always get called and an implementation that didn't call it would be non-standard. Am I right about that?
Yes and no. Indeed, the implementation that wouldn't call foo would be nonstandard. However, it doesn't have anything to do with sequence points.
The paragraph that would apply here would be 126.96.36.199/3:
In the abstract machine, all expressions are evaluated as speciﬁed by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object).