请注意,链接的问题具有根本不同的表达方式
x >= start && x++ <= end
它有根本的不同,因为这里的第二个子表达式有副作用。我会解释一下。
注意&&
is a 短路操作员 http://en.wikipedia.org/wiki/Short-circuit_evaluation。这意味着如果x >= start
评估为false
, 机器can分支过度评估x <= end
.
更准确地说,当编译器发出指令时x >= start && x <= end
, it can发出分支指令x <= end
when x >= start
评估结果为假。
不过,我强调使用这个词can在上述陈述中。这样做的原因是因为x <= end
没有副作用,因此编译器是否分支对其求值并不重要。
但是,如果第二个表达式确实对编译器有副作用must其上有分支。自从&&
是一个短路算子,在a && b
, if b
有任何副作用吗must not观察如果a
评估为false
;这是 C 和大多数(如果不是所有类 C 语言)短路的要求。
所以,特别是当你看
define POINT_IN_RANGE_AND_INCREMENT(p, range)
(p <= range.end && p++ >= range.start)
注意第二个表达式p++ >= range.start
有副作用。即,(后)递增p
by 1
。但这种副作用只有在以下情况下才能观察到:p <= range.end
评估为true
。因此,编译器must分支过度评估p++ >= range.start
if p <= range.end
评估结果为假。
产生分支的原因是因为机器要计算该表达式,它使用以下事实:if p <= range.end
评估为false
,那么它会自动知道整个表达式的计算结果为false
因此它不应该评价p++ >= range.start
因为它有副作用。因此,它must分支对表达式的第二部分求值。所以在装配中:
Ltmp1301:
ldr r1, [sp, #172] @ 4-byte Reload
ldr r1, [r1]
cmp r0, r1
bls LBB44_32
mov r6, r0 @ if the result of the compare is false
b LBB44_33 @ branch over evaluating the second expression
@ to avoid the side effects of p++
LBB44_32:
ldr r1, [sp, #188] @ 4-byte Reload
adds r6, r0, #1
Ltmp1302:
ldr r1, [r1]
cmp r0, r1
bhs LBB44_36
深感亏欠奥利·查尔斯沃斯 https://stackoverflow.com/users/129570/oli-charlesworth寻求有见地的评论。