哪位 PHP 大神来解答一下优先级和结合性的问题???

2017-12-13 00:13:41 +08:00
 SimbaPeng
php version: 7.0.26
不要问我这个问题有什么意义,谢谢,我只是单纯的想弄清楚 php 的优先级和结合性问题!!!


首先来看一个例子:
>>> $i = 1;
=> 1
>>> $i + $i++;
=> 3

这个很好理解,++优先级高于+, $i++这个表达式的值为 1,虽然是后置递增但$i++在跟$i 相加之前$i 已经完成了自增,所以是 2+1=3。


再看一个例子:
>>> $i = 1;
=> 1
>>> $i + ++$i + $i++;
=> 6

那谁能告诉我这个例子为什么等于 6 ?

按照我的算法:

1.应该先算最右边的$i++, 因为++优先级高于+, 然后++的结合性是从右到左,那么$i++这个表达式的值为 1,然后$i 递增为 2

2.然后算++$i, $i 自增为 3,++$i 表达式的值也为 3

3.然后就是 3 + 3 + 1 = 7

想不通为什么等于 6,求大神解答。



还有个问题:
>>> function foo(){ return 0; }
>>> if (!$a = foo()) { echo 1; }
1⏎

为什么这个例子不会报错?!的优先级不是比=号高么,为什么不是先算!$a???
虽然官方文档说这种操作是允许的,但是这到底算什么啊,feature?
3663 次点击
所在节点    PHP
34 条回复
wwww961h
2017-12-13 00:23:31 +08:00
!$a == foo()少了个=号,
SimbaPeng
2017-12-13 00:27:50 +08:00
@wwww961h 你可能没 get 到点,就是=号,他会把 foo()的返回值给$a, 再算!$a 的真假
shiny
2017-12-13 00:32:24 +08:00
@SimbaPeng 如果 f ( (!$a) = foo()) 就语法错误了
SimbaPeng
2017-12-13 00:33:50 +08:00
@shiny 是啊,我就是问为什么不报错,!的优先级比=高,不用打括号就该先算阿
shiny
2017-12-13 00:38:45 +08:00
@SimbaPeng 手册里加了 note,这算是个例外,原因不知道。http://php.net/manual/zh/language.operators.precedence.php
gbin
2017-12-13 01:26:24 +08:00
++$i 表达式为 2,表达式的取值为自增之前的值。是这样吧?
gbin
2017-12-13 01:30:59 +08:00
gbin
2017-12-13 01:35:44 +08:00
#6,#7 瞎了,没看到 APPEND。请忽略!
hjzx050935
2017-12-13 01:40:22 +08:00
http://www.php-internals.com/book/?p=chapt02/02-03-01-lex-and-yacc

深入一点可以看看 php 怎么生成抽象语法树的
jfcherng
2017-12-13 02:02:37 +08:00
居然允許 `if (!$a = foo()) { echo 1; } `... 根本是個坑
abusizhishen
2017-12-13 02:38:29 +08:00
对应的值是 2+3+1=6,数字的大小也是计算的顺序
ryd994
2017-12-13 04:25:57 +08:00
死背这个真没用
多写括号,良好缩进,自己方便,看的人也方便
zjsxwc
2017-12-13 08:39:32 +08:00
看文档: https://secure.php.net/manual/en/language.operators.increment.php

$i + ++$i + $i++;
= ($i + ++$i + $i), ($i+=1)
=2 + 2 + 2
zjsxwc
2017-12-13 08:44:46 +08:00
$i*1 + ++$i + $i++;
的结果是 5

还是多谢几行代码好了, 这种晦涩的表达式完全是自己找死
sagaxu
2017-12-13 09:05:34 +08:00
写了十几年代码,也没弄明白这种事情。因为我是多语言用户,要考虑这种写法在不同语言之间的差异,还要提防未定义行为,干脆就避开不用了,反正括号和换行不要钱
lights
2017-12-13 09:08:08 +08:00
从第一天学代码,我从来不主动写这样晦涩难懂的代码。
WytheHuang
2017-12-13 10:29:02 +08:00
还是加括号吧, 有时候真的难以理解的
```
$i = 1;
echo $i + $i + $i++; // 3
$i = 1;
echo $i + $i++ + $i; // 5
```
wwww961h
2017-12-13 23:51:20 +08:00
@SimbaPeng 个人认为,如果一直纠结这些东西,你这辈子不需要提升了,还是研究点有用的东西吧,
humpy
2017-12-15 16:32:50 +08:00
要知道这个表达式「$i + $i++ + ++$i 」的求值顺序,应用三条语法规则就清楚了:

1. 「+」 是双目运算符
2. 同一表达式中多个「+」 的结合方向是从左到右「同一行中的运算符具有相同优先级,此时它们的结合方向决定求值顺序」
3. 递增「 i++/++i 」优先级高于 「+」

所以这个表达式的求值顺序即为:
1. $i + $i++
= $i++ + $i
= 1 + 2
= 3

2. 3 + ++$i
= ++$i + 3
= 3 + 3
= 6

实际上你将它们的 opcode dump 出来就很清晰了:
L2 #0 EXT_STMT
L2 #1 ASSIGN $a 1
L4 #2 EXT_STMT
L4 #3 POST_INC $a ~1
L4 #4 ADD $a ~1 ~2
L4 #5 PRE_INC $a @3
L4 #6 ADD ~2 @3 ~4
L4 #7 ECHO ~4
L6 #8 RETURN 1
SimbaPeng
2017-12-15 17:47:54 +08:00
@humpy ++的结合性是从右到左,为什么不是先算 ++$i 呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/414247

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX