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

时间:2012-03-14 20:31:25

标签: php math operator-precedence

如果我试试这个:

$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

但为什么不是输出?

13 个答案:

答案 0 :(得分:112)

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

请参阅example 1,其中包含:

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

注意:

  1. 运算符优先级确定评估顺序。运算符优先级仅确定表达式$l + ++$l被解析为$l + (++$l),但不确定是否首先计算+运算符的左或右操作数。如果首先计算左操作数,则结果为0 + 1,如果首先计算右操作数,则结果为1 + 1.

  2. 操作员关联性也不确定评估顺序。 +运算符左侧关联性仅确定$a+$b+$c被评估为($a+$b)+$c。它不确定单个运算符的操作数的评估顺序。

  3. 同样相关:在this bug report关于另一个带有未定义结果的表达式,PHP开发人员说:“我们不保证评估的顺序[...],就像C没有。你能指出吗?到文档的任何地方,表明首先评估第一个操作数?“

答案 1 :(得分:66)

preincrement运算符“++”发生在它所评估的表达式的其余部分之前。实际上它是:

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

答案 2 :(得分:24)

a + b

a = 1
b = ++a

:= 2

你为什么期待别的什么?

在PHP中:

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

Operator precedence可视化:

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

可视化评估序列:

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

或写出:

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


为了好玩:

$a++ + ++$a

结果也是2。但是,如果将其作为表达式进行比较,则不等于:

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

在哪里

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

是“平等的”。


另见:

答案 3 :(得分:7)

我的Evaluation Order in PHP博文详细解释了这一点,但这里有一个基本想法:

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

答案 4 :(得分:6)

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

现在l = 1.

所以1 + 1 = 2.

答案 5 :(得分:3)

当你执行++ $ l(preincrement)时,它会在你加入之前完成 - > check operator precedence)。

因此,$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。

答案 6 :(得分:2)

可以通过检查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)的左手表达式时,它已经递增,因为++$a首先被评估。

显然,这种行为应not be relied upon;用这种方式的任何语言。

答案 7 :(得分:1)

检查增量操作员手册:

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

答案 8 :(得分:1)

您可能知道我们有两个增量运算符,一个是预增量,第二个是后增量。在表达式中使用之前,预增量会增加整数的值,另一方面,在表达式中使用后,增量增加值会增加。

假设您有变量$ a和变量$ b,如下所示

$ A = 0;

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

,而

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

答案 9 :(得分:1)

您的代码输出因PHP版本as seen here

而异
  

4.3.0 - 5.0.5的输出   1
  1

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

  

5.1.0的输出 - 5.5.0alpha4
  2
  1

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

这符合interjay's answer,在PHP中无法保证子表达式的评估顺序。输出 可能 1, 1的假设是正确的,那么声称输出 可能的答案也是正确的 1, 2

答案 10 :(得分:0)

第一个显而易见的部分是++的优先级高于+

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

的精益
$a = $l;
$b = ++$l;
return $a + $b;

答案 11 :(得分:0)

如前所述,x ++和++ x存在差异。你可以用

的方式解释它
x++;
分号后

递增

++x;

评估表达式时增加

所以看来你的表达式是从右到左评估的

echo $l + ++$l;
  1. 获取$ l: $ l = 0
  2. 申请++: ++ $ l = 1
  3. 获取$ l: $ l = 1
  4. 申请+: $ l + $ l = 1 + 1 = 2

答案 12 :(得分:-2)

所有陈述均从右到左执行。 因此,该值首先递增,而变量值= 1,因此1 + 1 = 2