Por que os operadores bit a bit têm prioridade mais baixa que as comparações?

63

Alguém poderia explicar a lógica, por que, em várias linguagens mais populares (veja a nota abaixo), os operadores de comparação (==,! =, <,>, <=,> =) Têm prioridade mais alta que os operadores bit a bit (&, |, ^ , ~)?

Acho que nunca encontrei um uso em que essa precedência fosse natural. Sempre são coisas como:

  if( (x & MASK) == CORRECT ) ...   // Chosen bits are in correct setting, rest unimportant

  if( (x ^ x_prev) == SET )      // only, and exactly SET bit changed

  if( (x & REQUIRED) < REQUIRED )   // Not all conditions satisfied

Os casos em que eu usaria:

  flags = ( x == 6 | 2 );     // set bit 0 when x is 6, bit 1 always.

estão quase inexistentes.

Qual foi a motivação dos designers de linguagem para decidirem sobre essa precedência dos operadores?


Por exemplo, todos, exceto o SQL nos 12 principais idiomas, são semelhantes aos da lista de Popularidade da Linguagem de Programação em langpop.com: C, Java, C ++, PHP, JavaScript, Python, C #, Perl, SQL, Ruby, Shell, Visual Basic.

SF.
fonte
16
erro na concepção original de volta em C
catraca aberração
7
@gnat, qual é o sentido dessa queixa? O OP não disse "todos", apenas "um monte de idiomas mais populares". E a grande maioria segue essa ordem. Nesta tabela, apenas um dos top 12 (SQL) não: langpop.com
3
O @ dan1111 point é, naturalmente, ajudar os respondentes a entender melhor a pergunta e fornecer melhores respostas. Veja bem, este não é um lugar para The Guessing Game - ou, como a página da turnê diz: "Não é um fórum de discussão. Não há conversa fiada".
mosquito
7
@gnat, concordo com a sua preocupação com jogos de adivinhação, mas não acho que isso se qualifique quando quase todos os idiomas populares exibem o comportamento descrito.
5
@ Dunk: A abordagem comum "por palpite" é [arithmetics] [logic operator] [arithmetics]. A maioria dos programadores não cria uma confusão de parênteses if(((x+getLowX()) < getMinX) || ((x-getHighX())>getMaxX())))- a maioria assumirá precedência da aritmética sobre a lógica e escreverá if( ( x + getLowX() < getMinX ) || ( x - getHighX() > getMaxX() )) assumindo precedência +acima <. Agora, intuitivamente, if( x ^ getMask() != PATTERN ) deve se comportar da mesma maneira, sendo o XOR o operador aritmético. O fato de ser interpretado como if( x ^ ( getMask() != PATTERN ) )completamente contra-intuitivo.
SF.

Respostas:

72

Os idiomas copiaram isso de C, e para C, Dennis Ritchie explica que, inicialmente, em B (e talvez no início de C), havia apenas uma forma &que, dependendo do contexto, era um bit a bit e / ou lógica. Posteriormente, cada função obteve seu operador: &para o bit a bit e &&para o lógico. Então ele continua

Sua introdução tardia explica uma infelicidade das regras de precedência de C. Em B escreve-se

if (a == b & c) ...

verificar se aé igual be cé diferente de zero; em tal expressão condicional, é melhor &ter precedência menor que ==. Ao converter de B para C, deseja-se substituir &por &&tal declaração; para tornar a conversão menos dolorosa, decidimos manter a precedência do &operador igual em relação a ==, e simplesmente dividir a precedência de &&ligeiramente de &. Hoje, parece que seria preferível mover as precedências relativas de &e ==, assim, simplificar um idioma C comum: para testar um valor mascarado em relação a outro valor, é preciso escrever

if ((a & mask) == b) ...

onde os parênteses internos são necessários, mas facilmente esquecidos.

AProgrammer
fonte
1
Isso não falharia se c=2Ou a==bresultasse ~0e não 1?
SF.
Parece que a == b retorna 0 ou 1, consulte cm.bell-labs.com/cm/cs/who/dmr/kbman.html .
AProgramador
Verifique a referência na resposta e leia o texto anterior.
SShaheen
1
@MasonWheeler: Especialmente em sistemas embarcados, às vezes é necessário usar macros semelhantes a funções [em alguns casos, elas podem oferecer um desempenho de ordem de magnitude melhor que as funções em linha e em alguns sistemas embarcados que podem ser críticos]. A declaração variável dentro dessas macros não é possível; o uso de uma variável global em uma macro pode funcionar, mas parece realmente nojento.
supercat
6
@MasonWheeler: Você pode encontrar um Raspberry Pi ou Arduino por US $ 0,50 na quantidade 1000?
Super8
7

Operadores bit a bit estão relacionados a operadores lógicos conceitualmente e na aparência, o que provavelmente explica por que eles estão próximos um do outro na tabela de precedência. Talvez alguém possa até argumentar que seria confuso &ser maior do que ==, e ainda &&assim menor ==.

Depois que um precedente de precedência (!) Foi definido, provavelmente era melhor para outros idiomas segui-lo por uma questão de consistência.

No entanto, costumo concordar com você que isso não é o ideal. No uso real, os operadores de bits são mais parecidos com operadores matemáticos do que lógicos, e seria melhor se eles fossem agrupados com os operadores matemáticos em precedência.


fonte