Приоритет оператора
Приоритет оператора определяет, насколько "тесно" он связывает между собой два выражения. Например, выражение 1 + 5 * 3 вычисляется как 16, а не 18, поскольку оператор умножения ("*") имеет более высокий приоритет, чем оператор сложения ("+"). Круглые скобки могут использоваться для принудительного указания порядка выполнения операторов. Например, выражение (1 + 5) * 3 вычисляется как 18.
Если операторы имеют равный приоритет, то будут ли они выполняться справа налево или слева направо определяется их ассоциативностью - смотрите примеры ниже.
В следующей таблице приведен список операторов, отсортированный по убыванию их приоритетов. Операторы, размещенные в одной строке имеют одинаковый приоритет и порядок их выполнения определяется исходя из их ассоциативности.
Ассоциативность | Оператор | Дополнительная информация |
---|---|---|
неассоциативна | clone new | clone и new |
левая | [ | array() |
правая | ++ -- ~ (int) (float) (string) (array) (object) (bool) @ | типы и increment/decrement |
неассоциативна | instanceof | типы |
правая | ! | логические операторы |
левая | * / % | арифметические операторы |
левая | + - . | арифметические операторы и строковые операторы |
левая | << >> | побитовые операторы |
неассоциативна | < <= > >= | операторы сравнения |
неассоциативна | == != === !== <> | операторы сравнения |
левая | & | побитовые операторы и ссылки |
левая | ^ | побитовые операторы |
левая | | | побитовые операторы |
левая | && | логические операторы |
левая | || | логические операторы |
левая | ? : | тернарный оператор |
правая | = += -= *= /= .= %= &= |= ^= <<= >>= => | операторы присваивания |
левая | and | логические операторы |
левая | xor | логические операторы |
левая | or | логические операторы |
левая | , | множество применений |
У операторов с равным приоритетом левая ассоциативность
подразумевает, что выражение вычисляется слева направо,
правая ассоциативность, соответственно, подразумевает противоположный порядок.
Неассоциативные операторы с равным приоритетом не могут комбинироваться сами
с собой. Например, выражение 1 < 2 > 1 в PHP недопустимо,
тогда как выражение 1 <= 1 == 1 корректно, потому что
оператор T_IS_EQUAL
имеет меньший приоритет, чем
оператор T_IS_SMALLER_OR_EQUAL
.
Пример #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
// при совместном использовании ++ и + результат будет неопределенным
$a = 1;
echo ++$a + $a++; // может вывести 4 или 5
?>
Замечание:
Несмотря на то, что оператор = имеет низший приоритет, чем большинство остальных операторов, PHP все равно позволяет использовать следующую конструкцию: if (!$a = foo()), которая присваивает переменной $a результат выполнения функции foo().
Коментарии
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
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.
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!
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.
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.
The precedence of '->' is less than '[' in this situation: object contains array, name of array is stored in string variable.
<?php
$farm = new StdClass;
$farm->emu = array( 'name' => 'Henry', 'age' => 9 );
$farm->rabbit = array( 'name' => 'George', 'age' => 4 );
$animal = 'rabbit';
print_r( $farm->$animal ); // ok
// print( $farm->$animal[ 'name' ] ); // wrong, [ has precedence.
print( $farm->{$animal}[ 'name' ] ); // correct, prints George.
$farm->wash = 'Suds';
$jobs = array( 'morning' => 'feed', 'evening' => 'wash' );
print( $farm->$jobs[ 'evening' ] ); // correct, prints Suds.
print( $farm->{$jobs[ 'evening' ]} ); // correct, prints Suds.
?>
<?php
// Another tricky thing here is using && or || with ternary ?:
$x && $y ? $a : $b; // ($x && $y) ? $a : $b;
// while:
$x and $y ? $a : $b; // $x and ($y ? $a : $b);
?>
If you've come here looking for a full list of PHP operators, take note that the table here is *not* complete. There are some additional operators (or operator-ish punctuation tokens) that are not included here, such as "->", "::", and "...".
For a really comprehensive list, take a look at the "List of Parser Tokens" page: tokens
Syntax (new Person())->talk(); is supported as of PHP 5.5
<?php
class A {
public $b = 'B';
public function b(){
return 'Bee';
}
}
$a = new A;
new $a->b();// This means new B() rather than new Bee()
?>
null coalescing `??` is between logic or `||` and ternary `? :`