©
This document uses PHP Chinese website manual Release
运算符优先级指定了两个表达式绑定得有多“紧密”。例如,表达式 1 + 5 * 3 的结果是 16 而不是 18 是因为乘号(“*”)的优先级比加号(“+”)高。必要时可以用括号来强制改变优先级。例如:(1 + 5) * 3 的值为 18。
如果运算符优先级相同,其结合方向决定着应该从右向左求值,还是从左向右求值——见下例。
下表按照优先级从高到低列出了运算符。同一行中的运算符具有相同优先级,此时它们的结合方向决定求值顺序。
结合方向 | 运算符 | 附加信息 |
---|---|---|
无 | clone new | clone 和 new |
左 | [ | array() |
右 | ++ -- ~ (int) (float) (string) (array) (object) (bool) @ | 类型和递增/递减 |
无 | instanceof | 类型 |
右 | ! | 逻辑运算符 |
左 | * / % | 算术运算符 |
左 | + - . | 算术运算符和字符串运算符 |
左 | << >> | 位运算符 |
无 | == != === !== <> | 比较运算符 |
左 | & | 位运算符和引用 |
左 | ^ | 位运算符 |
左 | | | 位运算符 |
左 | && | 逻辑运算符 |
左 | || | 逻辑运算符 |
左 | ? : | 三元运算符 |
右 | = += -= *= /= .= %= &= |= ^= <<= >>= => | 赋值运算符 |
左 | and | 逻辑运算符 |
左 | xor | 逻辑运算符 |
左 | or | 逻辑运算符 |
左 | , | 多处用到 |
对具有相同优先级的运算符,左结合方向意味着将从左向右求值,右结合方向则反之。对于无结合方向具有相同优先级的运算符,该运算符有可能无法与其自身结合。举例说,在 PHP
中 1 < 2 > 1 是一个非法语句,而 1 <= 1 == 1
则不是。因为 T_IS_EQUAL
运算符的优先级比
T_IS_SMALLER_OR_EQUAL
的运算符要低。
Example #1 结合方向
<?php
$a = 3 * 3 % 5 ; // (3 * 3) % 5 = 4
$a = true ? 0 : true ? 1 : 2 ; // (true ? 0 : true) ? 1 : 2 = 2
$a = 1 ;
$b = 2 ;
$a = $b += 3 ; // $a = ($b += 3) -> $a = 5, $b = 5
// mixing ++ and + produces undefined behavior
$a = 1 ;
echo ++ $a + $a ++; // may print 4 or 5
?>
Note:
尽管 = 比其它大多数的运算符的优先级低,PHP 仍旧允许类似如下的表达式:if (!$a = foo()),在此例中 foo() 的返回值被赋给了 $a 。
[#1] karlisd at gmail dot com [2015-11-10 17:39:51]
Sometimes it's easier to understand things in your own examples.
If you want to play around operator precedence and look which tests will be made, you can play around with this:
<?php
function F($v) {echo $v." "; return false;}
function T($v) {echo $v." "; return true;}
IF (F(0) || T(1) && F(2) || F(3) && ! F(4) ) {
echo "true";
} else echo " false";
?>
Now put in IF arguments f for false and t for true, put in them some ID's. Play out by changing "F" to "T" and vice versa, by keeping your ID the same. See output and you will know which arguments actualy were checked.
[#2] nicoolasens at gmail dot com [2015-10-22 09:17:17]
Too add something ton Antistone's comment :
{Antistone ?
1 year ago
BEWARE: Addition, subtraction, and string concatenation have equal precedence!
<?php
$x = 4;
echo "x minus one equals " . $x-1 . ", or so I hope";
?>
will print "-1, or so I hope"
(Concatenate the first string literal and the value of $x, then implicitly convert that to a number (zero) so you can subtract 1 from it, then concatenate the final string literal.)
}
You can use the operator "," instead of ".".
This way allows you to concatenate the first string literal after $x-1.
So the first string literal is note convert to a number (zero) .
Solution :
<?php
$x = 4;
echo "x minus one equals " , $x-1 . ", or so I hope";
?>
will print :
"x minus one equals 3, or so I hope "
[#3] fabmlk [2015-06-02 17:41:22]
Watch out for the difference of priority between 'and vs &&' or '|| vs or':
<?php
$bool = true && false;
var_dump($bool); // false, that's expected
$bool = true and false;
var_dump($bool); // true, ouch!
?>
Because 'and/or' have lower priority than '=' but '||/&&' have higher.
[#4] Anonymous [2015-05-10 11:33:59]
The following example will output false
$a = 1;
$b = 1;
$c = $a + $a++;
$d = 1 + $b++;
if($c == $d){
echo 'true';
}else{
echo 'false';
}
[#5] Antistone [2014-02-27 23:46:31]
BEWARE: Addition, subtraction, and string concatenation have equal precedence!
<?php
$x = 4;
echo "x minus one equals " . $x-1 . ", or so I hope";
?>
will print "-1, or so I hope"
(Concatenate the first string literal and the value of $x, then implicitly convert that to a number (zero) so you can subtract 1 from it, then concatenate the final string literal.)
[#6] leipie at gmail dot com [2013-06-12 09:35:17]
The precedence of the arrow operator (->) on objects seems to the highest of all, even higher then clone.
But you can't wrap (clone $foo)->bar() like this!
[#7] Carsten Milkau [2012-07-06 12:06:54]
Beware the unusual order of bit-wise operators and comparison operators, this has often lead to bugs in my experience. For instance:
<?php if ( $flags & MASK == 1) do_something(); ?>
will not do what you might expect from other languages. Use
<?php if (($flags & MASK) == 1) do_something(); ?>
in PHP instead.
[#8] headden at karelia dot ru [2009-06-09 04:02:45]
Although example above already shows it, I'd like to explicitly state that ?: associativity DIFFERS from that of C++. I.e. convenient switch/case-like expressions of the form
$i==1 ? "one" :
$i==2 ? "two" :
$i==3 ? "three" :
"error";
will not work in PHP as expected