Dennis Ritchie sobre as prioridades de && || vs. == etc. (1982)

A precedência de operadores para operadores booleanos e bitwise em C e linguagens relacionadas — especialmente `&&`, `||`, `&`, `|` e `==` — é examinada como uma fonte antiga de bugs sutis e confusão. Os comentaristas analisam as razões históricas que Dennis Ritchie deu para escolhas como fazer `&` ter precedência menor que `==`, e as contrastam com intuições matemáticas de álgebra booleana, teoria dos conjuntos e probabilidade. Muitos defendem o uso de parênteses explícitos ou de designs de linguagem que restrinjam expressões ambíguas, observando que linguagens mais novas e linters favorecem cada vez mais a clareza em vez de depender de regras de precedência memorizadas.

Principal confusão: precedência dos operadores lógicos

  • Muitos admitem que não se lembram de forma confiável de && vs || (e muitas vezes de AND/OR do SQL), e preferem sempre colocar parênteses em expressões mistas.
  • Outros argumentam que os desenvolvedores devem simplesmente aprender as regras, comparando a precedência de &&/|| com */+.
  • Vários observam que até quem conhece as regras é pego de surpresa ao alternar entre linguagens em que a precedência difere (por exemplo, shells).

Aritmética, álgebra booleana e mnemônicos

  • Vários comentários relacionam && à multiplicação e || à adição para valores 0/1: produto = AND, soma (saturada) = OR.
  • Outros preferem teoria dos conjuntos: && como interseção, || como união, com leis distributivas espelhando a álgebra booleana.
  • Alguns apontam que XOR se alinha de forma mais direta com adição na aritmética módulo 2, mas a analogia ainda ajuda a lembrar a precedência relativa.

Parênteses como estilo e segurança

  • Há um grupo forte a favor de parênteses explícitos em qualquer expressão booleana não trivial, mesmo quando a precedência é conhecida.
  • Argumentos:
    • Mais fácil para leitores futuros e revisores de código.
    • Evita bugs sutis quando expressões são editadas ou copiadas.
    • Linters que alertam sobre expressões no estilo a && b || c são bem-vindos depois de bugs reais.
  • Contra-argumentos:
    • Parênteses demais adicionam ruído e carga cognitiva; eles devem indicar overrides, não reafirmar padrões.
    • == true / == false desnecessários e excesso de parênteses são vistos como sinais de compreensão fraca.

Precedência entre bitwise e comparação em C (“o verdadeiro” tópico de Ritchie)

  • Esclarecimento de que o artigo original trata principalmente de por que &/| bitwise têm precedência mais baixa que == e similares, e não de && vs ||.
  • Historicamente, & era usado para AND lógico antes de && existir, então a==b & c==d precisava se comportar logicamente; essa escolha depois fez expressões como addr & mask == 0 serem analisadas de modo pouco intuitivo como addr & (mask == 0).
  • Os comentaristas concordam que isso é amplamente considerado um erro de projeto, mas foi preservado por compatibilidade retroativa.

Alternativas de design de linguagem

  • Algumas linguagens exigem parênteses ao misturar diferentes operadores infixos (Ada para operadores lógicos; Pony, parcialmente Zig, WGSL, abordagens no estilo Carbon).
  • Outras evitam ou minimizam a precedência (Smalltalk da esquerda para a direita; Lisp/Scheme via notação prefixa).
  • Linguagens mais novas ou estritamente tipadas ajustam a precedência (Go/Rust/Swift, Python) ou fundem operadores bitwise/lógicos de maneira controlada (por exemplo, Sail), muitas vezes com short-circuiting em booleanos.