Cómo la precedencia del operador C descifra su código (y cómo solucionarlo)

4

Escribe lo que quieres decir. El compilador lee lo que quiere.

Si alguna vez ha mirado fijamente una línea de código C, convencido de que estaba haciendo una cosa, sólo para ver cómo hace algo completamente distinto, ha cumplido con la precedencia de los operadores. No es un error. Es una característica del lenguaje que molesta incluso a los desarrolladores experimentados.

Tome esta aritmética simple:

x=5+3*6;

La clase de matemáticas dice sumar primero. C dice que no. La multiplicación y la división se encuentran en un nivel más alto que la suma y la resta. El compilador primero multiplica 3 por 6. Luego suma 5. X obtiene 23. No 48. Acabas de perder puntos en un examen. O peor aún, un despliegue de producción.

La confusión se profundiza cuando se mezclan operadores con sintaxis.

Mire esta declaración:

char *a[10];

¿Es “a” un puntero a una matriz de 10 caracteres? ¿O es una serie de 10 punteros a personajes?

Sin conocer las reglas de precedencia específicas, estás adivinando. En C, los corchetes [] se unen más estrechamente que los punteros *. Entonces esta es una matriz de 10 punteros a caracteres.

Esto es importante porque C no analiza como el inglés. Se analiza como una jerarquía rígida.

Puedes escribir código que parezca correcto pero que falle silenciosamente debido a la precedencia.

Considere la aritmética de punteros combinada con el acceso a estructuras.

*pi = 10;

Esto no funciona como se esperaba. El operador de punto . tiene mayor prioridad que el operador de desreferencia *. El compilador intenta acceder al miembro “i” del objeto señalado por “p” antes de eliminar la referencia a “p”. Pero “p” es un puntero, no una estructura. El compilador se ahoga. O peor aún, interpreta la memoria de una manera que corrompe los datos.

Hay que forzar el asunto.

(*p).i = 10;

Los paréntesis ganan. Siempre.

La jerarquía de operadores

Kernighan y Ritchie, los arquitectos de C, establecieron el precedente en su texto clásico. La siguiente tabla muestra el orden. La línea superior es la más alta. La parte inferior es la más baja.

  1. Paréntesis () y Subíndice []
  2. De izquierda a derecha.
  3. Operadores unarios ++, --, +, -, !, ~, (tipo), * (desreferencia), & (dirección), sizeof
  4. De derecha a izquierda.
  5. Multiplicativo *, /, %
  6. De izquierda a derecha.
  7. Aditivo +, -
  8. De izquierda a derecha.
  9. Mayús <<, >>
  10. De izquierda a derecha.
  11. Relacional <, <=, >, >=
  12. De izquierda a derecha.
  13. Igualdad ==, !=
  14. De izquierda a derecha.
  15. Bit a bit Y &
  16. De izquierda a derecha.
  17. XOR bit a bit ^