为什么 PHP 在与数组索引中的 $b++ 一起使用时对 $b 和 $b = $b 的计算不同

Why does PHP evaluate $b and $b = $b differently when used with $b++ in array index

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

我已经阅读了 SO 上的一些问题并检查了 PHP manual。这样做我开始明白 "PHP does not (in the general case) specify in which order an expression is evaluated""the behavior can change between versions of PHP or depending on the surrounding code"。不过,我认为这不适用于这种情况。或者是吗?

作为第一个承认这可能不是您日常编码问题的人,我仍然很好奇。偶然发现它试图做一些 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

这看起来像 manual 中用于演示未定义求值顺序 的示例。来自手册:

Operator precedence and associativity only determine how expressions are grouped, they do not specify an order of evaluation. PHP does not (in the general case) specify in which order an expression is evaluated and code that assumes a specific order of evaluation should be avoided, because the behavior can change between versions of PHP or depending on the surrounding code.

已强调

他们举的例子:

<?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++ 被确定为 first,而在第二个示例中索引 [=12] =] 是第一个。

NB

至于为什么这是,我相信同一手册页上的注释解释了一个可能的原因:

Although = has a lower precedence than most other operators, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the return value of foo() is put into $a.

我相信他们遗漏了一个关键的最后一个词:first(没有,对我来说,阅读笔记失去了一点意义)。

根据PHP自己的规则,我们假设一个FIFO顺序,!$a应该首先被评估。如果 $a 当前为 nullundefined,则 !$a 将等于 true(将对其求值并丢弃该结果)。之后,foo() 将被评估,其 return 值将被分配给 $a (即使我们假设 FIFO,如果其结果必须首先评估 foo()是要分配给某物)。此赋值的结果将由 if 计算,结果将与作者想要的完全相反。

我不是 C 语言专家,但通过一些搜索也找到了这个 answer,它引用了 C90 标准:

(C90, 6.3) "Except as indicated by the syntax or otherwise specified later (for the function-call operator (), &&, ||, ?:, and comma operators). the order of evaluation of subexpressions and the order in which side effects take place are both unspecitied"

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