查看在线执行结果: https://3v4l.org/HFmA7
要想了解下面代码的结果,有三点需要了解:
- ++$a 是自己加1,之后的都要加1;如果是指针引用,有些版本会导致 ++$a 的临时值为自身,让之前的计算结果也改变。
- $a++ 是自己不用增1的结果,但是这个操作符之后的都要加1,不管有没有指针引用。
- 编译器每一次都要把表达式组合成两元组:((($a++ + $a) + $a) + $a),但是在 ($a + $a++) 的情况下,会改变顺序为 ($a++ + $a),所以 $a++ + $a 的结果是3.
下面是 $a = 1; $b = &$a; echo ++$a + ++$a + $a;
的 vld 编码,可以看出具体的流程。
(php v7.0)
compiled vars: !0 = $a, !1 = $b
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > ASSIGN !0, 1
3 1 ASSIGN_REF !1, !0
4 2 PRE_INC $4 !0
3 PRE_INC $5 !0
4 ADD ~6 $4, $5
5 ADD ~7 ~6, !0
6 ECHO ~7
5 7 ECHO !0
8 > RETURN 1
from: https://3v4l.org/fgLZO/vld#tabs
不同的php 版本不同,导致的结果不同。我用 c++ 测试过,gcc 和 clang 的结果也不同(当然会有warning).
++a;++a
, clang 结果是6, gcc 结果是5
总结:
- 目前hhvm和7.0.0+都不再会受到指针引用的影响。(受影响的版本 5.1.1 - 5.6.24)
- 混写的写法:不易查错,不易 debug,全语言混乱
- 建议所有自增尽量用新行写
- 《PHP 一个诡异的加法算法的研究》 https://segmentfault.com/a/1190000005821745
- 《Analysis of some weird evaluation order in PHP》 https://gist.github.com/nikic/6699370
- 《Operator Precedence》http://php.net/manual/en/language.operators.precedence.php