当数组索引中使用$ b ++时,为什么PHP会以不同的方式评估$ b和$ b = $ b

时间:2015-04-01 19:51:35

标签: php operator-precedence

我无法掌握下面列出的代码中的评估逻辑。有谁知道为什么PHP在这种情况下评估$b$b = $b的方式不同?

我已在SO上阅读了一些问题并检查了PHP manual。这样做我已经明白“PHP没有(在一般情况下)指定表达式的评估顺序”“行为可以在PHP版本之间改变或者取决于周围的代码“。我不认为这适用于这种情况。或者是吗?

作为第一个承认这可能不是您日常编码问题的人,我仍然很好奇。偶然发现它试图做一些code golfing

$a = [[00, 01, 02, 03],
      [10, 11, 12, 13],
      [20, 21, 22, 23],
      [30, 31, 32, 33]];

$b = 2;
echo $a[$b][$b++], PHP_EOL;

$b = 2;
echo $a[$b=$b][$b++], PHP_EOL;

输出 - PHP 5.5.14:

32
22

1 个答案:

答案 0 :(得分:10)

这看起来像用于演示未定义评估顺序manual中的示例。从手册:

  

运算符优先级和关联性仅确定表达式的分组方式,它们不指定评估顺序。 PHP不会(在一般情况下)指定表达式的计算顺序和代码假设应该避免使用特定的评估顺序,因为行为可以在PHP版本之间或根据周围的代码进行更改。

强调添加

他们给出的例子:

<?php
$a = 1;
echo $a + $a++; // may print either 2 or 3

$i = 1;
$array[$i] = $i++; // may set either index 1 or 2
?>

您正在获得输出,因为在第一个示例中,索引$b++正在确定第一个,而在第二个示例中,索引$b=$b是第一个。

NB

至于为什么这是,我相信一个可能的原因可以通过同一手册页上的这个说明来解释:

  

尽管=的优先级低于大多数其他运算符,但PHP仍然允许使用类似于以下的表达式:if(!$ a = foo()),在这种情况下,foo()的返回值放入$ a

我相信他们在那里错过了一个至关重要的最后一句话: first (没有,对我来说读这个音符会失去一些意义)。

遵循PHP自己的规则,我们假设一个FIFO顺序,应首先评估!$a。如果$a目前为nullundefined,则!$a将等于true(将对其进行评估,结果将被丢弃)。接下来,将评估foo(),并将其返回值分配给$a(即使我们假设FIFO,如果要分配其结果,则必须首先评估foo()某事)。此作业的结果将由if进行评估,并且会产生与作者想要的完全相反的值。

我不是C专家,但是一些搜索也引导我answer引用了C90标准:

  

(C90,6.3)“除非语法指示或稍后指定(对于函数调用运算符(),&amp;&amp;,||,?:和逗号运算符)。评估顺序子表达式和副作用发生的顺序都是未指明的“

由于PHP是基于C构建的,因此它会继承它的一些怪癖。