运算符优先级

运算符的优先级指定它将两个表达式“紧密地”绑定在一起的方式。例如,在表达式 1 + 5 * 3 中,答案是 16 而不是 18,因为乘法(“*”)运算符的优先级高于加法(“+”)运算符。必要时,可以使用括号强制优先级。例如:(1 + 5) * 3 计算结果为 18

当运算符具有相同的优先级时,它们的结合性决定运算符的组合方式。例如,“-”是左结合的,所以 1 - 2 - 3 组合为 (1 - 2) - 3 并计算结果为 -4。“=”另一方面是右结合的,所以 $a = $b = $c 组合为 $a = ($b = $c)

具有相同优先级的非结合运算符不能彼此相邻使用,例如 1 < 2 > 1 在 PHP 中是非法的。另一方面,表达式 1 <= 1 == 1 是合法的,因为 == 运算符的优先级低于 <= 运算符。

结合性仅对二元(和三元)运算符有意义。一元运算符要么是前缀,要么是后缀,因此该概念不适用。例如,!!$a 只能组合为 !(!$a)

使用括号,即使在严格不需要时,也可以通过明确地进行分组,而不是依赖于隐式运算符优先级和结合性,从而提高代码的可读性。

下表按优先级顺序列出了运算符,优先级最高的运算符位于顶部。同一行上的运算符具有相同的优先级,在这种情况下,结合性决定分组。

运算符优先级
结合性 运算符 其他信息
(n/a) clone new clonenew
** 算术
(n/a) + - ++ -- ~ (int) (float) (string) (array) (object) (bool) @ 算术(一元 +-)、自增/自减位运算类型转换错误控制
instanceof 类型
(n/a) ! 逻辑
* / % 算术
+ - . 算术(二元 +-)、数组字符串(在 PHP 8.0.0 之前为 .
<< >> 位运算
. 字符串(从 PHP 8.0.0 开始)
非结合 < <= > >= 比较
非结合 == != === !== <> <=> 比较
& 位运算引用
^ 位运算
| 位运算
&& 逻辑
|| 逻辑
?? 空值合并
非结合 ? : 三元(在 PHP 8.0.0 之前为左结合)
= += -= *= **= /= .= %= &= |= ^= <<= >>= ??= 赋值
(n/a) yield from yield from
(n/a) yield yield
(n/a) print print
and 逻辑
xor 逻辑
or 逻辑

示例 #1 结合性

<?php
$a
= 3 * 3 % 5; // (3 * 3) % 5 = 4
// 三元运算符的结合性与 C/C++ 不同
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (在 PHP 8.0.0 之前)

$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
?>

运算符优先级和结合性只决定表达式的分组方式,它们不指定求值顺序。PHP(在一般情况下)不指定表达式的求值顺序,应避免假定特定求值顺序的代码,因为行为可能会在 PHP 版本之间发生变化,或者取决于周围的代码。

示例 #2 未定义的求值顺序

<?php
$a
= 1;
echo
$a + $a++; // 可能打印 2 或 3

$i = 1;
$array[$i] = $i++; // 可能设置索引 1 或 2
?>

示例 #3 +-. 具有相同的优先级(在 PHP 8.0.0 之前)

<?php
$x
= 4;
// 这行代码可能导致意外输出:
echo "x minus one equals " . $x-1 . ", or so I hope\n";
// 因为它像这行代码一样进行求值(在 PHP 8.0.0 之前):
echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
// 可以使用括号来强制执行所需的优先级:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
?>

上面的示例将输出

-1, or so I hope
-1, or so I hope
x minus one equals 3, or so I hope

注意:

虽然 = 的优先级低于大多数其他运算符,但 PHP 仍然允许类似于以下的表达式:if (!$a = foo()),在这种情况下,foo() 的返回值将放入 $a 中。

变更日志

版本 说明
8.0.0 字符串连接(.)现在的优先级低于算术加/减(+-)和按位左移/右移(<<>>);以前它与 +- 具有相同的优先级,并且优先级高于 <<>>
8.0.0 三元运算符(? :)现在是非结合的;以前它是左结合的。
7.4.0 依赖于字符串连接(.)相对于算术加/减(+-)或按位左移/右移(<<>>)的优先级,即在未加括号的表达式中一起使用它们,已被弃用。
7.4.0 依赖于三元运算符(? :)的左结合性,即嵌套多个未加括号的三元运算符,已被弃用。
添加注释

用户贡献注释 8 个注释

fabmlk
9 年前
注意 'and 与 &&' 或 '|| 与 or' 之间的优先级差异。
<?php
$bool
= true && false;
var_dump($bool); // false,预期结果

$bool = true and false;
var_dump($bool); // true,意外!
?>
因为 "and/or" 的优先级低于 "=",而 "||/&&" 的优先级更高。
aaronw at catalyst dot net dot nz
7 年前
如果您来这里是为了寻找 PHP 运算符的完整列表,请注意,此处的表格 *不* 完整。这里没有包含一些额外的运算符(或运算符式的标点符号),例如 "->"、"::" 和 "..."。

要查看一个真正全面的列表,请查看 "解析器令牌列表" 页面:https://php.net/manual/en/tokens.php
rvwoens at gmail dot com
1 年前
请注意,?? 的优先级较低,因此可能会导致意外结果

$a=[];
$a['aa']??'not set'
--> not set(预期结果)


"lets see if it is set".$a['aa']??'not set'
--> 注意:未定义的索引 aa
--> lets see if it is set

所以你需要使用括号
"lets see if it is set".($a['aa']??'not set')
Carsten Milkau
12 年前
注意位运算符和比较运算符的非寻常顺序,这在我的经验中经常会导致错误。例如

<?php if ( $flags & MASK == 1) do_something(); ?>

不会像你从其他语言中期望的那样工作。使用

<?php if (($flags & MASK) == 1) do_something(); ?>

在 PHP 中代替。
sangala at seznam dot cz
1 年前
使用强制转换和三元运算符可能不清楚,
(了解以下内容很有用:declare(strict_types = 1))。
<?php
$num_str
="5";

$i1 = (int) isset($num_str) ? $num_str : 0;
$i2 = (int) (isset($num_str) ? $num_str : 0);
var_dump($i1);
var_dump($i2);
?>
输出
string(1) "5"
int(5)
ivan at dilber dot info
7 年前
<?php
// 这里另一个棘手的事情是将 && 或 || 与三元 ?: 结合使用
$x && $y ? $a : $b; // ($x && $y) ? $a : $b;

// 而:
$x and $y ? $a : $b; // $x and ($y ? $a : $b);

?>
tlili dot mokhtar at gmail dot com
2 年前
一个获取左移运算符(<<)结果的简单技巧,例如

15 << 2 = 15 * (2*2) = 60

15 << 3 = 15 * (2*2*2) = 120

15 << 5 = 15 * (2*2*2*2*2) = 480

等等...

所以是

(左边的数字)乘以(右边的数字)乘以 2。

右移运算符(>>)也是一样的,其中

(左边的数字)除以(右边的数字)乘以 2,例如

15 >> 2 = (15/2)/2 = 7/2 = 3(如果结果是十进制,则使用 floor 值)。

35 >> 3 = (((35/2)/2)/2 = (17/2)/2 = 8/2 = 4
instatiendaweb at gmail dot com
3 年前
// 不正确
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2
// 不支持无括号的 `a ? b : c ? d : e`。请使用 `(a ? b : c) ? d : e` 或 `a ? b : (c ? d : e)`
// 正确
$a = (true ? 0 : true) ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2

==> 更正文档。
To Top