Dennis Ritchie sobre las prioridades de && || frente a ==, etc. (1982)

La precedencia de operadores booleanos y bit a bit en C y lenguajes relacionados —en particular `&&`, `||`, `&`, `|` y `==`— se examina como una fuente antigua de errores sutiles y confusión. Los comentaristas revisan las razones históricas que Dennis Ritchie dio para decisiones como hacer que `&` tenga menor precedencia que `==`, y las contrastan con intuiciones matemáticas de álgebra booleana, teoría de conjuntos y probabilidad. Muchos abogan por usar paréntesis explícitos o por diseños de lenguajes que restrinjan expresiones ambiguas, señalando que los lenguajes más nuevos y los linters favorecen cada vez más la claridad frente a depender de reglas de precedencia memorizadas.

Confusión principal: precedencia de los operadores lógicos

  • Muchos admiten que no recuerdan de forma fiable && frente a || (y a menudo también AND/OR de SQL), y prefieren poner siempre paréntesis en expresiones mixtas.
  • Otros sostienen que los desarrolladores simplemente deberían aprender las reglas, comparando la precedencia de &&/|| con la de */+.
  • Varios señalan que incluso quienes conocen las reglas se equivocan al cambiar de lenguaje donde la precedencia difiere (por ejemplo, en shells).

Aritmética, álgebra booleana y mnemotecnias

  • Varios comentarios relacionan && con la multiplicación y || con la suma para valores 0/1: producto = AND, suma (saturada) = OR.
  • Otros prefieren la teoría de conjuntos: && como intersección, || como unión, con leyes distributivas que reflejan el álgebra booleana.
  • Algunos señalan que XOR encaja de forma más limpia con la suma en aritmética módulo 2, pero la analogía sigue ayudando a recordar la precedencia relativa.

Paréntesis como estilo y seguridad

  • Fuerte apoyo a usar paréntesis explícitos en cualquier expresión booleana no trivial, incluso si se conoce la precedencia.
  • Argumentos:
    • Más fácil para lectores futuros y revisores de código.
    • Evita errores sutiles cuando las expresiones se editan o copian.
    • Se agradecen los linters que advierten sobre expresiones del estilo a && b || c tras errores reales en producción.
  • Contraargumentos:
    • Demasiados paréntesis añaden ruido y carga cognitiva; deberían indicar excepciones, no repetir lo que ya es el valor por defecto.
    • == true / == false innecesarios y el exceso de paréntesis se ven como señales de poca comprensión.

La precedencia de bit a bit frente a comparación en C (“el verdadero” tema de Ritchie)

  • Se aclara que el artículo original trata principalmente de por qué & y | bit a bit tienen menor precedencia que == y similares, no de && frente a ||.
  • Históricamente, & se usaba para AND lógico antes de que existiera &&, así que a==b & c==d debía comportarse lógicamente; esa elección hizo después que expresiones como addr & mask == 0 se interpretaran de forma poco intuitiva como addr & (mask == 0).
  • Los comentaristas coinciden en que esto se considera ampliamente un error de diseño, pero se mantuvo por compatibilidad hacia atrás.

Alternativas de diseño de lenguajes

  • Algunos lenguajes exigen paréntesis al mezclar distintos operadores infijos (Ada para operadores lógicos; Pony, parcialmente Zig, WGSL, enfoques al estilo Carbon).
  • Otros evitan o minimizan la precedencia (Smalltalk de izquierda a derecha; Lisp/Scheme mediante notación prefija).
  • Lenguajes estrictamente tipados o más nuevos ajustan la precedencia (Go/Rust/Swift, Python) o fusionan operadores bit a bit y lógicos de forma controlada (por ejemplo, Sail), a menudo con cortocircuito sobre booleanos.