La prioridad de los operadores
La prioridad de los operadores especifica el orden en el que deben ser analizadas las valores.
Por ejemplo, en la expresión 1 + 5 * 3
, el resultado es
16
y no 18
, ya que la multiplicación ("*") tiene una prioridad superior a la suma ("+").
Las parentesis pueden ser utilizados para forzar la prioridad, si es necesario. Por ejemplo: (1 + 5) * 3
dará
18
.
Cuando los operadores tienen una prioridad igual, su asociatividad decide la forma en que los operadores son agrupados. Por ejemplo,
"-" es una asociatividad por la izquierda, así 1 - 2 - 3
es agrupado de esta manera (1 - 2) - 3
y será evaluado
a -4
. Por otro lado, "=" es una asociatividad por la derecha, así, $a = $b = $c
es agrupado de esta manera
$a = ($b = $c)
.
Los operadores, cuya prioridad es igual, que no son asociativos, no pueden ser utilizados entre ellos, por ejemplo,
1 < 2 > 1
está prohibido en PHP. La expresión
1 <= 1 == 1
por el contrario, está permitida, ya que el operador
==
tiene una precedencia inferior al operador
<=
.
La asociatividad tiene sentido únicamente para los operadores binarios (y ternarios).
Los operadores unitarios son prefijos o sufijos, por lo que esta noción no es aplicable. Por ejemplo !!$a
puede ser agrupado únicamente de la siguiente manera !(!$a)
.
El uso de parentesis, incluso cuando no son necesarios, permite mejorar la legibilidad del código realizando agrupamientos explícitos en lugar de imaginar la prioridad de los operadores y sus asociatividades.
La tabla siguiente lista los operadores por orden de prioridad, con la prioridad más alta en la parte superior. Los operadores en la misma línea tienen una prioridad equivalente (por lo tanto, la asociatividad decide el agrupamiento).
Ejemplo #1 Asociatividad
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
// La asociatividad de los operadores ternarios difiere de C/C++
var_dump($a);
$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
var_dump($a, $b);
?>
El operador ternario requiere específicamente el uso de parentesis para levantar la ambigüedad de la prioridad.
Ejemplo #2 Precedencia explícita
<?php
$a = true ? 0 : (true ? 1 : 2);
var_dump($a);
// Esto ya no está permitido a partir de PHP 8
// $a = true ? 0 : true ? 1 : 2;
?>
La prioridad y la asociatividad del operador determinan únicamente la forma en que las expresiones son agrupadas; no especifican el orden de la evaluación. PHP no especifica (de manera general) el orden en que una expresión es evaluada y el código que asume un orden específico de evaluación no debería existir, ya que el comportamiento puede cambiar entre las diferentes versiones de PHP o según el código circundante.
Ejemplo #3 Orden de evaluación indefinido
<?php
$a = 1;
echo $a + $a++; // puede mostrar 2 o 3
$i = 1;
$array[$i] = $i++; // puede definir el índice 1 o 2
?>
Ejemplo #4 Precedencia de +
, -
y .
<?php
$x = 4;
// Esta línea puede causar una salida inesperada :
echo "x menos uno es igual a" . $x-1 . ", en todo caso espero\n";
// la precedencia deseada puede ser reforzada utilizando parentesis. :
echo "x menos uno es igual a" . ($x-1) . ", en todo caso espero\n";
// Esto no está permitido, y levanta una TypeError :
echo ("x menos uno es igual a" . $x) - 1 . ", en todo caso espero\n";
?>
El resultado del ejemplo sería:
-1, en todo caso espero
-1, en todo caso espero
Fatal error: Uncaught TypeError: Unsupported operand types: string - int
Ejemplo #5 Antes de PHP 8, +
, -
y .
tenían la misma precedencia
<?php
$x = 4;
// Esta línea puede causar una salida inesperada :
echo "x menos uno es igual a" . $x-1 . ", en todo caso espero\n";
// porque es evaluada como la línea siguiente (anterior a PHP 8.0.0) :
echo (("x menos uno es igual a" . $x) - 1) . ", en todo caso espero\n";
// la precedencia deseada puede ser reforzada utilizando parentesis. :
echo "x menos uno es igual a" . ($x-1) . ", en todo caso espero\n";
?>
El resultado del ejemplo sería:
-1, en todo caso espero
-1, en todo caso espero
x menos uno es igual 3, en todo caso espero
Nota:
Aunque =
tiene prioridad sobre la mayoría de los operadores, PHP ejecutará expresiones como: if (!$a = foo())
.
En esta situación, el resultado de foo()
será colocado en la variable $a.