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

Nea*_*eal 65 php math operator-precedence

如果我试试这个:

$a = 0;    
echo $a + ++$a, PHP_EOL;
echo $a;
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

2
1
Run Code Online (Sandbox Code Playgroud)

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

这是为什么?

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

1
1
Run Code Online (Sandbox Code Playgroud)

我的理解:

$a = 0;                    // a === 0    
echo $a + ++$a, PHP_EOL;   // (0) + (0+1) === 1
echo $a;                   // a === 1
Run Code Online (Sandbox Code Playgroud)

但为什么输出不是这样呢?

int*_*jay 113

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

参见示例1,其中说:

// mixing ++ and + produces undefined behavior
$a = 1;
echo ++$a + $a++; // may print 4 or 5
Run Code Online (Sandbox Code Playgroud)

笔记:

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

  2. 操作员关联性也不确定评估顺序.该+操作者已经离开结合性仅确定$a+$b+$c为被评估($a+$b)+$c.它不确定单个运算符的操作数的评估顺序.

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

  • @hakre:正确的部分不一定先评估.运算符优先级只决定在这里添加括号的位置,即`$ l + ++ $ l` - >`$ l +(++ $ l)`.但它不能确定是否首先评估`+`运算符的左侧或右侧. (2认同)

Den*_*nis 66

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

echo $l + ++$l; // (1) + (0+1) === 2
Run Code Online (Sandbox Code Playgroud)

  • 添加到这个:比较`echo $ l + $ l ++;`,它输出'1'作为OP期望的. (8认同)
  • @RyanP:参见[未定义的行为](http://stackoverflow.com/questions/949433/could-anyone-explain-these-undefined-behaviors-iiiii-etc) (8认同)
  • @Corbin运算符优先级并不能真正解释评估顺序,因为后缀和前缀++都具有相同的优先级,但不以相同的顺序进行求值. (3认同)
  • 边注; 是PHP的实际记录?我无法找到有关其评估顺序与表达式其余部分的任何内容. (2认同)

hak*_*kre 24

a + b

a = 1
b = ++a

:= 2
Run Code Online (Sandbox Code Playgroud)

你为什么期待别的什么?

在PHP中:

$a = 0;
$c = $a + ++$a;
Run Code Online (Sandbox Code Playgroud)

运算符优先级可视化:

$c = ($a) + (++$a);
Run Code Online (Sandbox Code Playgroud)

评估序列可视化:

$a = 0; ($a = 0)
$a = 1; (++$a)
$c = $a + $a (1 + 1);
Run Code Online (Sandbox Code Playgroud)

或写出来:

执行总和操作的时刻$a已经是1,因为++$a已经进行了评估.在++该操作前评估+操作.


为了好玩:

$a++ + ++$a
Run Code Online (Sandbox Code Playgroud)

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

$a++ + ++$a == $a + ++$a
Run Code Online (Sandbox Code Playgroud)

在哪里

$a++ + ++$a == $a-- + --$a 
Run Code Online (Sandbox Code Playgroud)

是平等的".


也可以看看:

  • @hakre你需要解释一下,你的答案没有意义. (3认同)

Nik*_*kiC 7

在PHP博客文章中的评估订单详细解释了这一点,但这里是基本的想法:

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


Joh*_*136 6

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

所以现在 l = 1.

所以 1 + 1 = 2.

  • 优先级仅确定分组.评估顺序是独立的. (3认同)
  • 实际上前缀和后缀++都是相同的优先级,因此优先级不应该与评估顺序有任何关系. (2认同)