Приоритет оператора указывает, насколько «тесно» он связывает вместе два выражения. Например, в выражении 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)
.
Использование круглых скобок, даже если это не является строго необходимым, часто может повысить читабельность кода, делая группировку явной, а не полагаясь на неявный приоритет операций и ассоциативность.
В следующей таблице перечислены операторы в порядке приоритета, причем операторы с наивысшим приоритетом находятся вверху. Операторы в одной строке имеют одинаковый приоритет, и в этом случае ассоциативность определяет группировку.
Associativity | Operators | Additional Information |
---|---|---|
(n/a) | clone new | clone and new |
right | ** | arithmetic |
(n/a) | + - ++ -- ~ (int) (float) (string) (array) (object) (bool) @ | arithmetic (unary + and - ), increment/decrement, bitwise, type casting and error control |
left | instanceof | type |
(n/a) | ! | logical |
left | * / % | arithmetic |
left | + - . | arithmetic (binary + and - ), array and string (. prior to PHP 8.0.0) |
left | << >> | bitwise |
left | . | string (as of PHP 8.0.0) |
non-associative | < <= > >= | comparison |
non-associative | == != === !== <> <=> | comparison |
left | & | bitwise and references |
left | ^ | bitwise |
left | | | bitwise |
left | && | logical |
left | || | logical |
right | ?? | null coalescing |
non-associative | ? : | ternary (left-associative prior to PHP 8.0.0) |
right | = += -= *= **= /= .= %= &= |= ^= <<= >>= ??= | assignment |
(n/a) | yield from | yield from |
(n/a) | yield | yield |
(n/a) | print | |
left | and | logical |
left | xor | logical |
left | or | logical |
Пример #1 Ассоциативность
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
// ternary operator associativity differs from C/C++
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (prior to 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++; // may print either 2 or 3
$i = 1;
$array[$i] = $i++; // may set either index 1 or 2
?>
Пример №3 +
и -
имеют .
такой же приоритет (до PHP 8.0.0)
<?php
$x = 4;
// this line might result in unexpected output:
echo "x minus one equals " . $x-1 . ", or so I hope\n";
// because it is evaluated like this line (prior to PHP 8.0.0):
echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
// the desired precedence can be enforced by using parentheses:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
?>
Приведенный выше пример выведет:
-1, или я надеюсь
-1, или я надеюсь, что
х минус один равно 3, или так я надеюсь
Примечание :
Хотя
=
имеет более низкий приоритет, чем большинство других операторов, PHP по-прежнему допускает выражения, подобные следующим:if (!$a = foo())
, и в этом случае возвращаемое значениеfoo()
помещается в $a .
0 комментариев