为什么是$ a + ++ $ a == 2?

如果我尝试这个:

$a = 0; echo $a + ++$a, PHP_EOL; echo $a; 

我得到这个输出:

 2 1 

演示: http : //codepad.org/ncVuJtJu

这是为什么?

我希望得到这个作为输出:

 1 1 

我的理解:

 $a = 0; // a === 0 echo $a + ++$a, PHP_EOL; // (0) + (0+1) === 1 echo $a; // a === 1 

但为什么不是输出?

所有解释你为什么得到2而不是1的答案实际上是错误的。 根据PHP文档,以这种方式混合+++是未定义的行为,所以你可以得到1或2.切换到不同的PHP版本可能会改变你得到的结果,这也是一样有效的。

见示例1 ,其中说:

 // mixing ++ and + produces undefined behavior $a = 1; echo ++$a + $a++; // may print 4 or 5 

笔记:

  1. 运算符优先级不决定评估的顺序。 运算符优先级只确定expression式$l + ++$l被parsing为$l + (++$l) ,但不确定是否首先计算+运算符的左边或右边的操作数。 如果左操作数首先被计算,结果将是0 + 1,如果右操作数被首先计算,结果将是1 + 1。

  2. 运算符关联性也不能确定评估顺序。 +运算符已经离开关联性只会确定$a+$b+$c被评估为($a+$b)+$c 。 它并不决定单个操作员操作数的评估顺序。

同样重要的是:在关于另一个expression式的错误报告中 ,一个PHP定义的结果,一个PHP开发人员说:“我们不保证评估顺序,就像C没有关系一样。在哪里声明第一个操作数是先评估的?

一个预先增加的运算符“++”发生在它所评估的expression式的其余部分之前。 所以它实际上是:

 echo $l + ++$l; // (1) + (0+1) === 2 
 a + b a = 1 b = ++a := 2 

你为什么期待别的东西?

在PHP中:

 $a = 0; $c = $a + ++$a; 

可视化运算符优先级 :

 $c = ($a) + (++$a); 

评估顺序可视化:

 $a = 0; ($a = 0) $a = 1; (++$a) $c = $a + $a (1 + 1); 

或者写出来:

总和操作执行的那一刻, $a已经是1,因为++$a已经被评估了。 ++运算符在+运算符之前被评估。


为了好玩:

 $a++ + ++$a 

结果也在2。 但是,如果将它作为expression式进行比较,则不等于:

 $a++ + ++$a == $a + ++$a 

在哪里

 $a++ + ++$a == $a-- + --$a 

是平等的”。


也可以看看:

  • PHP评估顺序(2013年9月,由NikiC提供) ( via

我在PHP博客文章中的评价命令详细解释了这一点,但这里是基本的想法:

  • 运算符优先级和关联性与评估顺序无关。
  • PHP不保证评估顺序。 订单可以在PHP版本之间更改,恕不另行通知,也可以根据周围的代码而有所不同。
  • “通常”PHP将从左到右评估,除了访问“简单”variables(如$a )。 对简单variables的访问将更复杂的expression式之后执行,无论expression式实际发生的顺序如何。
  • 在这种特殊情况下,这意味着++$a首先被运行,因为它是一个复杂的expression式,只有$a的值被提取(在这一点上它已经是1)。 所以有效地你正在求和1 + 1 = 2
  • 在复杂expression式之后获取简单variables的原因是编译variables(CV)优化。 如果禁用此优化,例如通过使用@错误抑制运算符,则所有expression式都将从左到右进行求值,包括简单variables提取。
  • 在这种特殊情况下,它意味着@($a + ++$a)将导致1 ,因为首先获取$a (当时为0),并且只在此之后才增加。

++是较高优先级的运算符,因此它首先被应用。

所以现在l = 1.

所以1 + 1 = 2.

当你执行你的++ $ l(预增量)时,它会在添加之前完成 – > 检查运算符优先级 )。

所以,在添加之前, $l的值将是1

 echo $l + ++$l; // $l => 1 because ++$l is done first 

所以你的答案是2。

但是,当你这样做:

 echo $l // you will get your first value which is $l => 1 

所以你的答案是1。

这个行为可以通过检查PHP编译你的脚本来确认,例如:

 $a = 0; echo $a + ++$a; 

编译成以下操作码,然后执行:

 compiled vars: !0 = $a line # * op fetch ext return operands --------------------------------------------------------------------------------- 1 0 > ASSIGN !0, 0 1 PRE_INC $1 !0 2 ADD ~2 !0, $1 3 ECHO ~2 4 > RETURN null 

这转换为以下等效的脚本:

 $a = 0; // ASSIGN $tmp = ++$a; // PRE_INC echo $a + $tmp; // ADD, ECHO 

结论

$a被评估为$a + (++$a)的左边expression式时,它已经被增加了,因为++$a首先被评估。

显然,这种行为不应该依靠 ; 在任何语言的事情。

检查增量操作员手册:

http://www.php.net/manual/en/language.operators.increment.php

或者看看这个键盘: http : //codepad.org/Y3CnhiLx

 <?php $n = 0; $m = 0; echo '++ before:'; echo $n+ ++$n; echo PHP_EOL; echo '++ after:'; echo $m+ $m++; echo PHP_EOL; echo 'n:'.$n; echo PHP_EOL; echo 'm:'.$m; 

输出:

 ++ before:2 ++ after:1 n:1 m:1 

你可能知道我们有两个增量运算符,一个是预增量,另一个是后增量。 预增量在expression式中使用之前增加整数的值,另一方面在expression式中使用之后增加数字的增量值。

假设你有如下的variables$ a和variables$ b

$ A = 0;

$ b = ++ $ a给出b = 1的值

$ b = $ a ++给出值b = 0

您的代码的输出随PHP版本而变化, 如此处所示

输出为4.3.0 – 5.0.5
1
1

在上述情况下, +运算符的左侧首先被评估(0,1,+)。

输出为5.1.0 – 5.5.0alpha4
2
1

在上述情况下, +运算符的右侧首先被评估(1,1,+)。

这符合interjay的回答 ,即在PHP中不能保证子expression式的评估顺序。 输出可能是 1, 1的假设是正确的,那些声称输出可能是 1, 2答案也是正确的。

第一个明显的部分是+++有更高的优先级。

第二部分是PHP引擎不会将第一个操作数的值存储到另一个匿名variables中。 所以$l + ++$l不是一个qeuivalent

 $a = $l; $b = ++$l; return $a + $b; 

如前所述,x ++和++ x有所不同。 你可以用这种方式解释它

 x++; 

分号后递增

 ++x; 

增加expression式的评估

所以看起来你的表情是从右到左评估的

 echo $l + ++$l; 
  1. 获取$ l: $ l = 0
  2. 应用++: ++ $ l = 1
  3. 获得$ l: $ l = 1
  4. 应用+: $ l + $ l = 1 + 1 = 2

所有的语句都是从右到左执行的。 所以这个值首先增加,比你的variables值= 1,所以1 + 1 = 2