Please note that the related question has a fundamentally different expression
x >= start && x++ <= end
This is fundamentally different because the second subexpression here has a side effect. I will explain.
Note that && is a short circuit operator . This means that if x >= start evaluates to false , the machine can go through the evaluation x <= end .
More precisely, when the compiler issues instructions for x >= start && x <= end , it can issue instructions to jump to x <= end when x >= start gets false.
However, I emphasize the use of the word can in the above statements. The reason for this is that x <= end has no side effects, and therefore it doesn’t matter if the compiler branches over its evaluation or not.
But in the event that the second expression has side effects, the compiler must expand it. Since && is a short circuit operator, in a && b , if b has any side effects, they should not be observed if a is evaluated to false ; this is a short circuit requirement in C and most (if not all C-like languages).
So, in particular, when you look
define POINT_IN_RANGE_AND_INCREMENT(p, range) (p <= range.end && p++ >= range.start)
note that the second expression p++ >= range.start has a side effect. Namely, (post), increasing p by 1 . But this side effect can only be observed if p <= range.end evaluates to true . Thus, the compiler must pass a score of p++ >= range.start if p <= range.end is false.
The reason this leads to the branch is because in order for the machine to evaluate this expression, it uses the fact that if p <= range.end evaluates to false , then it automatically knows that the whole expression evaluates as false , and therefore it should not evaluate p++ >= range.start because it has a side effect. Thus, it should branch out over the evaluation of the second part of the expression. So in the assembly:
Ltmp1301: ldr r1, [sp,
Oli Charlesworth deep indebtedness for insightful comments.