PRIORIDADES DE OPERADORES.







Tabla de prioridades de operadores.
Lo que sigue es la lista de operadores de C, ordenados según su prioridad. En caso de que una expresión contenga más de un operador de igual prioridad, la evaluación se realizará según el orden que se indica en la columna central. Por ejemplo, si se encuentran dos operadores de desplazamiento (>> y <<), la evaluación se hará de izquierda a derecha. Pero si se encuentran dos operadores de suma con asignación (+=), entonces la evaluación se realizará de derecha a izquierda (se evalúa primero la expresión situada más a la derecha).


Grupo de operadores Orden de evaluación Comentarios
() [] -> . de izquierda a derecha Este es el grupo de operadores con mayor prioridad.
! ~ ++ -- + - (tipo) * & sizeof de derecha a izquierda La refundición de tipos y sizeof son operadores unarios.
* / % de izquierda a derecha El símbolo "%" denota el operador módulo, que produce el resto entero obtenido al dividir el primer operando por el segundo.
+ - de izquierda a derecha Los operadores aditivos tienen menor prioridad que los multiplicativos.
<< >> de izquierda a derecha Estos son los operadores de desplazamiento bit a bit (q.v.)
< <= > >= de izquierda a derecha
== != de izquierda a derecha
& de izquierda a derecha Este operador y los dos siguientes realizan operaciones lógicas bit a bit, considerando bits individuales de sus operandos.
^ de izquierda a derecha
| de izquierda a derecha
&& de izquierda a derecha Este operador y el siguiente producen resultados lógicos, pero no consideran bits individuales sino el valor global del operando.
|| de izquierda a derecha
?: de derecha a izquierda
= += -= *= /= %= &= ^= |= <<= >>= de derecha a izquierda
, de izquierda a derecha Este es el operador de menor prioridad en C. Sirve para separar una colección de expresiones, que se irán evaluando de izquierda a derecha. El resultado es el producido por la expresión situada en último lugar (más a la derecha), y tiene por tanto el tipo y valor de esta última expresión. Se emplea a veces en expresiones de control; un ejemplo sería la cláusula de iniciación de un for o la cláusula de mantenimiento de iteración de un while.


Uso de paréntesis.
Cuando el compilador genera el código que se emplea para evaluar una expresión, hace uso de la información textual de que dispone, pero no "reconoce" la expresión, como puede hacerlo un ser humano. Las unicas reglas que se aplican son las de prioridad de operadores expuestas en la tabla anterior. Sin embargo, C nos permite especificar sin ambigüedad el orden de evaluación deseado; esto se hace empleando paréntesis. Los paréntesis que estén anidados con más profundidad serán los primeros en evaluarse. Veáse un ejemplo.

La idea es bien sencilla: el operador paréntesis fuerza la evaluación de su contenido, elevando su prioridad con respecto a todos los demás operadores, salvo el propio operador paréntesis en el caso de que se encuentre más profundamente anidado. Los paréntesis no estropean nada, y aseguran que el compilador entienda exactamente lo mismo que el programador. Cuando en una expresión aparecen dos o más subexpresiones entre paréntesis de igual prioridad, se realiza la evaluación de izquierda a derecha. Véase un ejemplo.

Operador de asignación: Distinción entre = y ==.
Es muy frecuente cometer el error consistente en confundir dos operadores distintos pero de aspecto similar: Estos dos operadores, binarios ambos, admiten como operandos dos expresiones, y producen un resultado. Este resultado es completamente distinto:Como puede apreciarse, las expresiones a = 7; y a == 7; producen resultados completamente distintos... pero existe un grave peligro. En efecto, ¿qué ocurre si se evalúa el resultado de estas expresiones desde el punto de vista lógico? Esto es, qué resultados obtendremos si se utiliza el resultado de estas expresiones como variable de control en una sentencia if():

if( a == 7)
  printf("a vale 7");
else
  printf("a no vale 7);
  
if (a = 7)
  printf("a vale 7");
else
  printf("a no vale 7);

Como puede observarse, en la primera expresión el resultado será siempre correcto: a == 7 solo es no nulo si a vale 7. Pero en la segunda, el resultado de evaluar a = 7 será siempre 7. Luego pasan dos cosas:
Como decíamos, esta es una fuente de errores muy común. El compilador no puede detectarlos, porque tanto a = 7 como a == 7 son expresiones completamente correctas. Afortunadamente, basta invertir el orden de la expresión para que el compilador detecte un error:
if( 7 == a)
  printf("a vale 7");
else
  printf("a no vale 7);
  
if (7 = a)
  printf("a vale 7");
else
  printf("a no vale 7);

La expresión 7 == a es válida; se tienen dos operandos para el operador de comparación. Pero la expresión 7 = a es sintácticamente incorrecta, porque 7 no es un nombre válido de variable. El compilador señala un error. Por tanto, para evitar este tipo de errores, debemos adoptar la costumbre de situar siempre las constantes a la izquierda cuando se utilice el operador "==". De este modo, si olvidamos un "=", el compilador detecta el error.

Asignaciones múltiples
Como se ha indicado, el resultado de una asignación es el valor de la expresión situada a la derecha. Esto permite escribir expresiones de la forma
a = b = c;
en donde primero se evalúa c; a continuación se asigna c a b, y por último se asigna b a a. Véase el oportuno Ejemplo.


Ejercicio.- Verificar las reglas de prioridad de operadores, empleando paréntesis para efectuar un cálculo elemental. Comprobar los resultados obtenidos tanto al emplear paréntesis como al no hacer uso de ellos.

#include <stdio.h>

void main(void)
{
  int cociente, a, b, c, d;
  printf ("Paréntesis y prioridad de operadores\n\n");
  cociente = 0;
  a = 10;   b = 4;  c = 5;  d = 1;
  cociente = (a*b)/(c+d);
  printf("Empleando paréntesis,cociente vale %d\n",cociente);
  cociente = 0;   a = 10;   b = 4;  c = 5;  d = 1;
  cociente = a*b/c+d;
  printf("Sin emplear paréntesis,cociente vale %d\n",cociente);
}

/*
  Resultados:
  
Paréntesis y prioridad de operadores

Empleando paréntesis,cociente vale 6
Sin emplear paréntesis,cociente vale 9

*/
Comentario.- El primer caso no tiene dificultad; los paréntesis hacen de igual prioridad los dos lados del rvalue y se evalúa la expresión de izquierda a derecha (véase el siguiente ejercicio). En el segundo caso, el operador de multiplicación y el de división tienen igual prioridad, y el operador suma tiene menor prioridad que los anteriores. Por tanto, se evalúan primero las subexpresiones relativas a operadores de mayor prioridad. Dado que la prioridad de * y / es la misma, se evalúa de izquierda a derecha, luego se calcula a*b. Acto seguido se divide el resultado por c. Por último, a*b/c se suma con d.


Ejercicio.- Estudiar la evaluación de expresiones a igualdad de prioridades, en el caso de paréntesis. Comprobar que la evaluación se efectúa de izquierda a derecha.

#include <stdio.h>

void main(void)
{
  int num, cociente, a, b, c, d;
  printf ("Evaluación de expresiones\n\n");
  a = 10; b = 4; c = 5; d = 1; num = 0;
  cociente = (num = a*b)/(num + c + d);
  printf("Cociente vale %d\n", cociente);
  printf("\n\nTerminación normal del programa.\n");
}
/*
Salida obtenida:
Evaluación de expresiones
Cociente vale 0
Terminación normal del programa.
*/

Comentario.- El resultado es 0, luego se evalúa de izquierda a derecha. Si fuera de derecha a izquierda,el denominador haría uso del valor nulo de num, y el resultado no sería cero sino 6.


Ejemplo.- Comprobar los resultados de una confusión entre el operador "=" y el operador "==".

#include <stdio.h>
void main(void)
{
  int a, b, c;
  printf ("Confusión del operador = con el operador ==\n\n");
  a = 1; b = 2; c = 3;
  a = b == c;
  printf("El resultado de comparar b = %d y c = %d es a = %d\n\n",
      b, c, a); 
  a = b = c;
  printf("El resultado de ASIGNAR c = %d a b = %d a a es a = %d\n\n", c, b, a);
  printf("\n\nTerminación normal del programa.\n\n");  
}

/*
Confusión del operador = con el operador ==

El resultado de comparar b = 2 y c = 3 es a = 0

El resultado de ASIGNAR c = 3 a b = 3 a a es a = 3

Terminación normal del programa.
*/

Comentarios.- Obsérvese que 0 denota falso, y 3 denota verdadero. Por tanto, la asignación daría lugar a un valor incorrecto para a, que no sería detectado.