我将问题缩小到此代码

$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个问题:
  • 为什么先执行后增量?这对我来说没有任何意义。传统上,我认为在表达式中执行所有其他操作后,它将使变量递增。这也是官方PHP网站上所说的。因此,按照我的逻辑(可能存在难以置信的缺陷),两个表达式都将返回10。但是正如我们所看到的,POST_INC在执行其他操作之前先执行。
  • 如我们所见,在 MUL 操作期间,对于第一种情况,〜2 应该是POST_INC的结果(因此值应为4),然后乘以3为12。但是在第二种情况下,其中!0 仍为3,而〜2 似乎也具有 3 的值,由于我未知的原因,所以最后得到9。为什么会这样?

  • 我不太会读操作码,所以也许我错过了一些东西,我猜测操作数〜2,3 vs !0,〜2 的顺序很重要,但我不知道怎么做。

    最佳答案

    此处的关键参与者是operator precedence,因此,尽管是表达式中的最后一个元素,但仍将$a++评估为首先(即$a之前)。请注意,post中的post increment表示该表达式(变量)的 Action 后评估,而整个表达式(代码行)的而不是评估。

    在您的第一种情况下,代码是这样的:

    $result = 3 * $a++;
    

    因此用于乘法的$a的值为3,因为它先被读取然后递增。该表达式中不再使用$a,因此$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
    

    一旦理解,这看起来就很清楚了,但另一方面,通过编写您认为知道其工作方式与实际工作方式的代码,它可以很好地展示出您可以多么聪明地超越自己:)因此,您要么需要仔细阅读语言文档,要么确保您知道,从而确定您编写的代码将执行什么操作,或者只是为了避免在以后的调试 session 中出于个人理智而编写过于“聪明”的代码:) KISS原则存在是有原因的。

    关于php - 后增量表演很奇怪,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59880917/

    10-09 01:56