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 deAND/ORdo 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 || csã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/== falsedesnecessá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ãoa==b & c==dprecisava se comportar logicamente; essa escolha depois fez expressões comoaddr & mask == 0serem analisadas de modo pouco intuitivo comoaddr & (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.