1
wwww961h 2017-12-13 00:23:31 +08:00
!$a == foo()少了个=号,
|
5
shiny 2017-12-13 00:38:45 +08:00
@SimbaPeng 手册里加了 note,这算是个例外,原因不知道。http://php.net/manual/zh/language.operators.precedence.php
|
6
gbin 2017-12-13 01:26:24 +08:00 via Android
++$i 表达式为 2,表达式的取值为自增之前的值。是这样吧?
|
7
gbin 2017-12-13 01:30:59 +08:00 via Android
|
8
gbin 2017-12-13 01:35:44 +08:00 via Android
#6,#7 瞎了,没看到 APPEND。请忽略!
|
9
hjzx050935 2017-12-13 01:40:22 +08:00
|
10
jfcherng 2017-12-13 02:02:37 +08:00
居然允許 `if (!$a = foo()) { echo 1; } `... 根本是個坑
|
11
abusizhishen 2017-12-13 02:38:29 +08:00 via Android
对应的值是 2+3+1=6,数字的大小也是计算的顺序
|
12
ryd994 2017-12-13 04:25:57 +08:00 via Android
死背这个真没用
多写括号,良好缩进,自己方便,看的人也方便 |
13
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 |
14
zjsxwc 2017-12-13 08:44:46 +08:00
$i*1 + ++$i + $i++;
的结果是 5 还是多谢几行代码好了, 这种晦涩的表达式完全是自己找死 |
15
sagaxu 2017-12-13 09:05:34 +08:00 via Android
写了十几年代码,也没弄明白这种事情。因为我是多语言用户,要考虑这种写法在不同语言之间的差异,还要提防未定义行为,干脆就避开不用了,反正括号和换行不要钱
|
16
lights 2017-12-13 09:08:08 +08:00 via iPhone
从第一天学代码,我从来不主动写这样晦涩难懂的代码。
|
17
WytheHuang 2017-12-13 10:29:02 +08:00
还是加括号吧, 有时候真的难以理解的
``` $i = 1; echo $i + $i + $i++; // 3 $i = 1; echo $i + $i++ + $i; // 5 ``` |
19
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 |
21
humpy 2017-12-15 18:09:16 +08:00
至于这个问题,
>>> function foo(){ return 0; } >>> if (!$a = foo()) { echo 1; } 1⏎ 刚才翻了一下源码,似乎是 parser 定义的锅... Zend/zend_language_parser.y : | '!' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2); } 「!$a = foo()」这条语句,在语法解析时,会先解析 「$a = foo()」为赋值语句,然后再匹配到 「'!' expr 」 另外,根据这里的语法定义,似乎「~」运算符也有同样的问题... |
24
humpy 2017-12-15 18:19:58 +08:00
@SimbaPeng 你对单目 /双目运算符的理解有一点偏差
单目运算符的意思就是它只需要一个 oprand 就可以组成一个表达式 双目运算符需要两个 oprand 对于这个表达式「$i + $i++ + ++$i 」,按照语法规则,转换一下就清晰了: $a = $i++ $b = ++$; $i + $i++ + ++$i = $i + $a + $b = ($i + $a) + $b |
25
SimbaPeng OP @humpy 单目 /双目运算符我知道,你还是没告诉我+号为什么会在第二个++之前运算?你这么说我好迷茫啊,我对优先级的理解是整个表达式中优先级最高的运算符先计算,然后依次计算优先级低的, 同级别按结合性。
比如: 2 + 3 * 2 + 4 / 2 这个表达式不是先算 3 * 2 再算 4 / 2 , 最后再相加吗? 难道是 先算 3 * 2 然后加上 2 , 再算 4 / 2,再相加? 虽然结果都一样 但是优先级到底是什么时候触发的? |
26
humpy 2017-12-15 23:11:21 +08:00
@SimbaPeng 我明白你的意思,但是对编程语言的求值顺序不能按自己的数学习惯套,你把运算符优先级和实际求值顺序搞混了。运算符优先级高不代表它的求值更早,优先级只是说明某些运算符比另一些运算符的「组合能力」更强,是中缀程序语言为了避免歧义的设计,它处于语法设计层面;求值顺序更多是语言实现层面的事,但因为求值过程中可能会产生副作用,为了避免程序员掉坑,所以文档里会写上。
这是顶楼表达式的语法树,求值顺序就是后序遍历的顺序;如果按照你所期望的顺序求值,你觉得应该怎么遍历这颗语法树呢? |
27
SimbaPeng OP @humpy 我明白了,一直以为优先级就是求值顺序,原来优先级只是确定操作数的组合方式,并不等于求值顺序,求值顺序是不确定的,副作用的发生时间也是不确定的,由编译器的行为所决定。除了 && || , 等等这些操作符。所以这题应该是没有答案,4,5,6,7 都可以。。。
|
28
xiaohanqing 2017-12-16 10:46:06 +08:00 via Android
写这样的东西就是坑自己,研究透了有什么用,就算 !$a 先执行也不是报错啊,就是个警告
|
29
SimbaPeng OP @xiaohanqing 研究透了才知道自己缺的是编译原理方面的知识懂吗?肯定得买本书补补了。写这种东西谁不知道是坑人?关键是自己不去弄懂这些东西就是坑自己,拈轻怕重谁不会?不知道不可怕,可怕的是自己根本不想去知道。
怕是也只有 php 在使用未定义的变量时只是报个 Notice。。。 |
31
SimbaPeng OP @sagaxu 谁说我从 php 中去悟了,php 的文档也不会去讲这些东西。我是看到 humpy 道友的解释,加上自己查 c 语言的书关于优先级那一张才弄明白的,只是刚好在 php 的这个问题上发现自己不足而已,php 的语法不规范刚好暴露了我自己对优先级理解的不透彻。没有疑惑就没一探究竟的动力。
|
32
cxbig 2017-12-17 09:12:37 +08:00
谁在工作中这样写逻辑的?
探索这些不如多来几个括号解决实际问题,至少别人审阅代码也不用想太多。 |
33
SimbaPeng OP @cxbig 我在整个帖子中有说过有人会在工作中这样写吗?还是我鼓励你们这样写了?我在这里请教一下语法层面的东西跟我在实际工作中如何去写有关系吗?有冲突吗?我在这里请教为什么,你们却过来告诉我怎么做?答非所问?语文理解能力差?
另外你要是觉得我在这讨论的东西在你眼里不值一提,你大可一笑而过,至少我看到<<C 程序设计语言>>这本书里用了一页纸来说明求值顺序和操作符的副作用。 |
34
mingyun 2017-12-17 20:20:19 +08:00
貌似面试喜欢考这些。。。
|