原:PHP 运算符的优先级
作者 斯人 | 发布于 2012 年 2 月 21 日

今天在群里无意间看到一个网友问的一个问题
$a=$b=0;
if($a=0 || $b =2)
{
var_dump($a,$b);
}

输出:
bool(true)
int(2)

谁能解释一下$a 为什么是true?

我对这个问题也挺好奇…开始没有想到优先级
后来用vld翻开PHP执行生成的OP来观察,才发现..是优先级的问题

number of ops:  12
compiled vars:  !0 = $a, !1 = $b
line     # *  op                           fetch          ext  return  operands
---------------------------------------------------------------------------------
   2     0  >   ASSIGN                                            RES[  IS_VAR $0 ]       OP1[  IS_CV !1 ] OP2[ ,  IS_CONST (0) 0 ]
         1      ASSIGN                                                    OP1[  IS_CV !0 ] OP2[ ,  IS_VAR $0 ]
   3     2    > JMPNZ_EX                                          RES[  IS_TMP_VAR ~2 ]       OP1[  IS_CONST (0) 0 ] OP2[ , ->5 ]
         3  >   ASSIGN                                            RES[  IS_VAR $3 ]       OP1[  IS_CV !1 ] OP2[ ,  IS_CONST (0) 2 ]
         4      BOOL                                              RES[  IS_TMP_VAR ~2 ]       OP1[  IS_VAR $3 ]
         5  >   ASSIGN                                            RES[  IS_VAR $4 ]       OP1[  IS_CV !0 ] OP2[ ,  IS_TMP_VAR ~2 ]
         6    > JMPZ                                                      OP1[  IS_VAR $4 ] OP2[ , ->11 ]
   4     7  >   SEND_VAR                                                  OP1[  IS_CV !0 ]
         8      SEND_VAR                                                  OP1[  IS_CV !1 ]
         9      DO_FCALL                                      2           OP1[  IS_CONST (34085885) 'var_dump' ]
   5    10    > JMP                                                       OP1[ ->11 ]
  15    11  > > RETURN                                                    OP1[  IS_CONST (0) 1 ]

下面这段代码

   2     0  >   ASSIGN                                            RES[  IS_VAR $0 ]       OP1[  IS_CV !1 ] OP2[ ,  IS_CONST (0) 0 ]
         1      ASSIGN                                                    OP1[  IS_CV !0 ] OP2[ ,  IS_VAR $0 ]

没有异议,如果熟悉PHP内核的人一看就知道 ASSIGN 就是给变量赋值
对应的是 $a=$b=0;
重点就在这里了

   3     2    > JMPNZ_EX                                          RES[  IS_TMP_VAR ~2 ]       OP1[  IS_CONST (0) 0 ] OP2[ , ->5 ]
         3  >   ASSIGN                                            RES[  IS_VAR $3 ]       OP1[  IS_CV !1 ] OP2[ ,  IS_CONST (0) 2 ]
         4      BOOL                                              RES[  IS_TMP_VAR ~2 ]       OP1[  IS_VAR $3 ]
         5  >   ASSIGN                                            RES[  IS_VAR $4 ]       OP1[  IS_CV !0 ] OP2[ ,  IS_TMP_VAR ~2 ]
         6    > JMPZ                                                      OP1[  IS_VAR $4 ] OP2[ , ->11 ]

||在PHP里被解析成JMPNZ_EX 这里先执行了||

 > JMPNZ_EX                                          RES[  IS_TMP_VAR ~2 ]       OP1[  IS_CONST (0) 0 ] OP2[ , ->5 ]

IS_TMP_VAR 是临时变量的意思 这里保存一个临时变量 ~2它的值是 0

ASSIGN                                            RES[  IS_VAR $3 ]       OP1[  IS_CV !1 ] OP2[ ,  IS_CONST (0) 2 ]

这句代码执行的是 $b=2; 然后保存到变量 $3里.
BOOL RES[ IS_TMP_VAR ~2 ] OP1[ IS_VAR $3 ]
$3与 临时变量~2比较
也就是执行了代码 $3||0 ,返回的值~2肯定是真

ASSIGN                                            RES[  IS_VAR $4 ]       OP1[  IS_CV !0 ] OP2[ ,  IS_TMP_VAR ~2 ]

最后 ~2的值 赋给$a;
这个时候 $a 和 $b的值都为真
那么 var_dump输出 true 也就是理所应当的事了..

原文出处:http://www.imsiren.com/archives/193