我正在阅读PHP手册的Operator Precedence部分。我很困惑(或者说,我不太了解以下句子):
运算符优先级和关联性仅确定表达式的分组方式,它们不指定评估顺序。 PHP(在一般情况下)不指定表达式的评估顺序,应避免使用假定特定评估顺序的代码,因为行为可以在PHP版本之间或根据周围代码进行更改。
它还提供了两个例子来说明未定义的评估顺序。
<?php
$a = 1;
echo $a + $a++; // may print either 2 or 3
>?
根据我的理解,$ a首先评估为1,因为剩下加法运算符的关联性。然后将1添加到$ a ++,其结果为1.那么,结果应为2.为什么文档中的注释说&#34;可以打印2或3&#34;?
第二个例子是:
<?
$i = 1;
$array[$i] = $i++; // may set either index 1 or 2
?>
类似地,$ i ++首先计算为1,因为赋值运算符的关联性是正确的。然后应将值1设置为数组的索引2。为什么评论说&#34;可以设置索引1或2&#34;?
我能想到的唯一解释是,上述两个例子中的代码顺序可以与我的推理相反。
任何能帮助我解开困惑的想法都将不胜感激。
答案 0 :(得分:1)
仅仅因为操作符是左关联的,它并不意味着从左到右评估参数。在
$a + $a++
它可以先评估$a
或先评估$a++
。在第一种情况下,结果是1 + 1 = 2
;在第二种情况下,结果是2 + 1 = 3
。
关联性只是指定多个表达式在组合时的分组方式。例如,如果你有
1 - 2 + 3
left-associativity指定将其解释为
(1 - 2) + 3 = 2
而不是
1 - (2 + 3) = -4
但如果这个表达式有副作用的子表达式,它仍然可以从右到左(或以某种混合顺序)评估它们。
答案 1 :(得分:1)
混乱涉及相关性。如果您说它适用,则没有相关性。
看看给出的例子:
$a = 1;
echo $a + $a++; // may print either 2 or 3
您可以通过两个步骤细分该表达式的评估:
$a
的值并计算$a++
优先规则对此有所说明:
$a++
的评估应在评估添加之前进行:++
的优先级高于+
但就是这样。
没有规则说明在评估$a
之前应检索$a++
的值。这不是左关联性的意思。
当两个具有相同优先级的运算符(例如,两个相同的运算符)在一个表达式中一个接一个地出现时,左(或右)关联性才起作用。例如
$a = 0
$a++ - 1 - $a++
第一个-
保证在第二个之前执行,由左关联性规则执行。
但是,这为以下评估序列留下了可能性:
$a++
$a++
所以,虽然关联性规则确定步骤4必须在步骤3之后,但没有规则规定前两步的顺序。
$i = 1;
$array[$i] = $i++; // may set either index 1 or 2
同样,这里没有左边的关联性。 PHP可以按任意顺序执行以下两个步骤:
$i++
$i
索引没有规则规定这应该发生的顺序。
如果声明是这样的话,那么正确的关联就会发挥作用:
$i = 1;
$array[$i] = $i = $i + 1; // may set either index 1 or 2
现在PHP必须按照它们的顺序执行以下步骤:
$i
$i
,产生其值$i
索引 Associativity希望步骤3和6按此顺序排列。数组元素不允许在“中间”$i
之前接收其值。但它并不妨碍PHP采用这种替代方案:
$i
索引$i
$i
,产生其值由于步骤5和6的顺序仍然正确,因此遵守关联性规则。结果仍然不同。
如果陈述是这样的话,左联结也将起作用:
$array[$i][$j] = $i++;
这非常简单,但[
的左关联性规则意味着首先使用最左边的索引从数组中检索元素,然后才能在结果数组中使用第二个索引。但请注意,这并不意味着必须在$i
之前评估$j
。
采取这种变化:
$i = 1;
$array[$i++][$i] = 13;
您不能假设元素$array[1][2]
将获得值13.它可能是$array[1][1]
。左派联想并没有说明这一点。然而,它确实说明了数组元素的检索(在这个结构中)必须从左到右完成。
在步骤中,这是一种可能的情况:
$i
:1 $i++
执行并产生1 步骤3和4必须按此顺序进行。它们甚至不必是相邻的步骤。这也允许PHP执行:
$i++
执行并产生1 $i
:2 步骤2发生在步骤4之前,因此不会破坏关联性规则。
即使Operators Precedence附近的陈述似乎有必要,但该条至少有一个关于优先权的错误,正如我在回答this question时所阐述的那样。