后增量表现怪异

我已将问题缩小到此代码


$a = 3;

$a = 3 * $a++;  

echo $a; //9


$a = 3;

$a = $a * $a++;  

echo $a; //12

这是第一次操作的 VLD 操作码


compiled vars:  !0 = $a

line     #* E I O op                           fetch          ext  return  operands

-------------------------------------------------------------------------------------

   2     0  E >   ASSIGN                                                   !0, 3

   3     1        POST_INC                                         ~2      !0

         2        MUL                                              ~3      ~2, 3

         3        ASSIGN                                                   !0, ~3

   4     4        ECHO                                                     !0

   5     5      > RETURN                                                   1

第二次操作 ($a * $a++)


compiled vars:  !0 = $a

line     #* E I O op                           fetch          ext  return  operands

-------------------------------------------------------------------------------------

   2     0  E >   ASSIGN                                                   !0, 3

   3     1        POST_INC                                         ~2      !0

         2        MUL                                              ~3      !0, ~2

         3        ASSIGN                                                   !0, ~3

   4     4        ECHO                                                     !0

   5     5      > RETURN                                                   1

2个问题:

  1. 为什么先执行后增量?这对我来说没有任何意义。传统上,我认为它会在执行表达式中的所有其他操作后增加变量。这也是 PHP 官方网站上所说的。因此,按照我的逻辑(这可能存在难以置信的缺陷),两个表达式都将返回 10。但正如我们所看到的,POST_INC 是在执行其他任何操作之前执行的。

  2. 正如我们所看到的,在MUL操作期间,对于第一种情况,~2应该是 POST_INC 的结果(所以值应该是 4),然后乘以 3 是 12。但在第二种情况下,!0仍然是3, ~2似乎也持有3的值,原因我不知道,所以我们最终得到 9。为什么会这样?

我不流利地阅读操作码,所以也许我错过了一些东西,我猜操作数的顺序~2, 3 vs !0, ~2很重要,但我不明白怎么做。


喵喵时光机
浏览 136回答 1
1回答

郎朗坤

这里的关键角色是运算符优先级,因此,尽管是表达式中的最后一个元素,但首先$a++计算(在 ie 之前)。请注意,其中的意思是对该表达式(变量)的操作后评估,而不是对整个表达式(代码行)的评估。$apostpost increment在您的第一种情况下,代码是这样的:$result = 3 * $a++;所以$a用于乘法的值是3因为它是先读取然后递增的。该表达式中不再$a使用,因此新值 of$a并不重要,除非$a再次引用,否则不会影响我们:     $a = 3$result = 3 * $a++        = 3 * 3                 // $a is 4 now        = 9第二种情况不同:$result = $a * $a++;因为我们对$a. 评估将是这样的:     $a = 3$result = $a * $a++        = $a * 3  // value of `$a` is 4 after post-increment                  // evaluation, and this affects us as we                   // evaluate $a again        = 4 * 3        = 12为了答案的完整性,让我们再添加一个案例:$result = $a++ * $a++;评估将类似地进行,$a最后具有不同的价值:     $a = 3$result = $a++ * $a++         // $a is 4 now        = 3 * $a++        = 3 * 4                 // $a is 5 now        = 12一旦你理解了这一点,这看起来很清楚,但另一方面很好地展示了你可以通过编写你认为你知道它是如何工作的代码而不是它的实际工作原理来轻松地超越自己 :) 所以你要么需要仔细阅读语言文档以确保您确定自己编写的代码会做什么,或者在未来的调试会话中为了个人理智而避免编写过于“聪明”的代码:) KISS原则的存在是有原因的。
打开App,查看更多内容
随时随地看视频慕课网APP