PHP - "运算符优先级和关联性没有指定评估顺序"意思?

时间:2016-02-08 19:43:20

标签: php

我正在阅读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;?

我能想到的唯一解释是,上述两个例子中的代码顺序可以与我的推理相反。

任何能帮助我解开困惑的想法都将不胜感激。

2 个答案:

答案 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

您可以通过两个步骤细分该表达式的评估:

  1. 获取$a的值并计算$a++
  2. 执行添加
  3. 优先规则对此有所说明:

    • $a++的评估应在评估添加之前进行:
      ++的优先级高于+

    但就是这样。

    没有规则说明在评估$a之前应检索$a++的值。这不是左关联性的意思。

    结合性

    当两个具有相同优先级的运算符(例如,两个相同的运算符)在一个表达式中一个接一个地出现时,左(或右)关联性才起作用。例如

    $a = 0
    $a++ - 1 - $a++
    

    第一个-保证在第二个之前执行,由左关联性规则执行。

    但是,这为以下评估序列留下了可能性:

    1. 评估第二个$a++
    2. 评估第一个$a++
    3. 评估第一次减法(需要在下一步之前发生)
    4. 评估第二次减法
    5. 所以,虽然关联性规则确定步骤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必须按照它们的顺序执行以下步骤:

      1. 评估(最右边)$i
      2. 执行添加
      3. 在中间分配给$i,产生其值
      4. 评估$i索引
      5. 检索已评估索引的数组元素
      6. 将值分配给该数组元素
      7. Associativity希望步骤3和6按此顺序排列。数组元素不允许在“中间”$i之前接收其值。但它并不妨碍PHP采用这种替代方案:

        1. 评估$i索引
        2. 检索已评估索引的数组元素
        3. 评估(最右边)$i
        4. 执行添加
        5. 在中间分配给$i,产生其值
        6. 将值分配给检索到的数组元素
        7. 由于步骤5和6的顺序仍然正确,因此遵守关联性规则。结果仍然不同。

          第二个例子,左侧关联性

          如果陈述是这样的话,左联结也将起作用:

          $array[$i][$j] = $i++;
          

          这非常简单,但[的左关联性规则意味着首先使用最左边的索引从数组中检索元素,然后才能在结果数组中使用第二个索引。但请注意,这并不意味着必须在$i之前评估$j

          采取这种变化:

          $i = 1;
          $array[$i++][$i] = 13;
          

          您不能假设元素$array[1][2]将获得值13.它可能是$array[1][1]。左派联想并没有说明这一点。然而,它确实说明了数组元素的检索(在这个结构中)必须从左到右完成。

          在步骤中,这是一种可能的情况:

          1. 评估第二次$i:1
          2. $i++执行并产生1
          3. 检索数组元素1(希望是一个数组)
          4. 元素1取自结果数组
          5. 步骤3和4必须按此顺序进行。它们甚至不必是相邻的步骤。这也允许PHP执行:

            1. $i++执行并产生1
            2. 检索数组元素1(希望是一个数组)
            3. 评估第二次$i:2
            4. 元素2取自结果数组
            5. 步骤2发生在步骤4之前,因此不会破坏关联性规则。

              优先条款

              的问题

              即使Operators Precedence附近的陈述似乎有必要,但该条至少有一个关于优先权的错误,正如我在回答this question时所阐述的那样。

相关问题