因此,我与一位同事讨论了评估执行的顺序。 考虑这个条件:
if (a > b && ref++) { do something }
我们都同意按照C标准,订单是从左到右。然而, 不同意见是,尽管有评估的顺序,但最终评估数据的一些指令可能会被推测性地执行,然后尽管进行了懒惰的评估,仍然保持这种状态。
例如,ref
在评估a > b
之前递增,评估仍然从左到右发生,即jump greater than
和{{a > b
的实际rev > 0
指令1}}从左到右依次执行,并在第一个实例时放弃!true。现在这违背了懒惰评估的整个概念,但如果ref
是指令流,内联函数可能会怎样。开始以推测方式执行某些指令会更有意义。关注的是:这些指示是否已经发生,甚至是中途。
思想?
答案 0 :(得分:8)
运营商&&
(以及运营商||
)在某种意义上是特殊的,因为它们保证了从左到右的“快捷评估”。这意味着,对于像expr1 && expr2
这样的条件,expr1
将始终首先进行评估,并且 - 甚至更多 - 如果expr2
已经评估为expr1
,则if (a > b && ref++)
将无法进行评估假。这不是优化,这是由语言保证的。
因此,在ref++
中,当且仅当ref
评估为a > b
时,才会评估表达式true
(包括递增ssh user1@gateway
的副作用) 。
答案 1 :(得分:1)
由于a > b && ref++
运营商短路,&&
无法实现。
想想那个案子:
f = fopen("foo.txt");
if ((f != NULL) && fread(buffer,10,1,f)) { ...
如果f==NULL
是错误,则执行第二部分,因为第一部分可以防止它。
相反,没有什么能阻止编译器在这里做任何想做的事情:
a > b & ref++
&
是算术和,因此始终执行这两个条件。因此,即使第一个条件为假,ref
也会递增。
答案 2 :(得分:1)
允许C编译器实现“as-if”规则,这意味着只要程序的 intent 得到尊重,他们就可以做任何他们喜欢的事情。
考虑(a > b && ref++)
。这里的意图是,如果ref
为a > b
,则1
仅 这是因为只有当左手参数为&&
时,才会评估1
的右手参数。但是,生成的汇编代码可能会使CPU可以推测性地增加ref
(分支预测),并在适当的情况下使用管道转储撤消该增量。