¿Por qué los operadores bit a bit tienen menor prioridad que las comparaciones?

63

¿Podría alguien explicar la razón, por qué en un grupo de idiomas más populares (ver nota más abajo) los operadores de comparación (==,! =, <,>, <=,> =) Tienen mayor prioridad que los operadores bit a bit (&, |, ^ , ~)?

No creo que haya encontrado un uso donde esta precedencia sea natural. Siempre son cosas 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

Los casos en los que usaría:

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

son casi inexistentes.

¿Cuál fue la motivación de los diseñadores de idiomas para decidir sobre la precedencia de los operadores?


Por ejemplo, todos menos SQL en los 12 idiomas principales son similares en la lista de popularidad del lenguaje de programación en langpop.com: C, Java, C ++, PHP, JavaScript, Python, C #, Perl, SQL, Ruby, Shell, Visual Basic.

SF.
fuente
16
error en el diseño original en C
monstruo de trinquete
77
@gnat, ¿cuál es el punto de esa queja? El OP no dijo "todos", solo "algunos de los idiomas más populares". Y la gran mayoría sigue este orden. En esta tabla, solo uno de los 12 principales (SQL) no: langpop.com
3
El punto @ dan1111 es, naturalmente, ayudar a los respondedores a comprender mejor la pregunta formulada y proporcionar mejores respuestas. Verá, este no es un lugar para The Guessing Game , o, como dice la página de la gira , "No es un foro de discusión. No hay charla".
mosquito
77
@gnat, estoy de acuerdo con tu preocupación sobre los juegos de adivinanzas, pero no creo que esto califique cuando casi todos los idiomas populares exhiben el comportamiento descrito.
55
@Dunk: El enfoque común "por presentimiento" es [arithmetics] [logic operator] [arithmetics]. La mayoría de los programadores no crean un lío de paréntesis como if(((x+getLowX()) < getMinX) || ((x-getHighX())>getMaxX()))): la mayoría asumirá la precedencia de la aritmética sobre la lógica y escribirá if( ( x + getLowX() < getMinX ) || ( x - getHighX() > getMaxX() )) asumiendo la precedencia de lo +anterior <. Ahora, intuitivamente, if( x ^ getMask() != PATTERN ) debería comportarse igual, siendo XOR un operador aritmético. El hecho de que se interpreta if( x ^ ( getMask() != PATTERN ) )es completamente contra-intuitivo.
SF.

Respuestas:

72

Los lenguajes lo han copiado de C, y para C, Dennis Ritchie explica que inicialmente, en B (y tal vez al principio de C), solo había una forma &que, según el contexto, era una bit a bit o lógica. Más tarde, cada función obtuvo su operador: &para el bit a bit y &&para el lógico. Entonces él continúa

Su introducción tardía explica una infelicidad de las reglas de precedencia de C. En B uno escribe

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

para verificar si aes igual by cno es cero; en una expresión tan condicional, es mejor que &tenga menor prioridad que ==. En la conversión de B a C, se quiere sustituir &por &&una declaración; para que la conversión sea menos dolorosa, decidimos mantener la precedencia del &operador en relación con la misma ==, y simplemente dividimos la precedencia de &&ligeramente &. Hoy, parece que hubiera sido preferible mover las precedentes relativas de &y ==, y por lo tanto, simplificar un lenguaje C común: para probar un valor enmascarado contra otro valor, uno debe escribir

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

donde se requieren los paréntesis internos pero se olvidan fácilmente.

Un programador
fuente
1
¿No fallaría eso si c=2O a==bresultara ~0y no 1?
SF.
Parece que a == b devuelve 0 o 1, consulte cm.bell-labs.com/cm/cs/who/dmr/kbman.html .
Programador del
Verifique la referencia en la respuesta y lea el texto anterior.
SShaheen
1
@MasonWheeler: Especialmente en sistemas embebidos, a veces es necesario usar macros con funciones similares [en algunos casos, pueden ofrecer un rendimiento de órdenes de magnitud mejor que las funciones en línea, y en algunos sistemas embebidos que pueden ser críticos]. La declaración variable dentro de tales macros no es posible; El uso de una variable global dentro de una macro podría funcionar, pero parece realmente asqueroso.
supercat
66
@MasonWheeler: ¿Puedes encontrar una Raspberry Pi o Arduino por $ 0.50 en la cantidad 1000?
supercat
7

Los operadores bit a bit están relacionados con operadores lógicos tanto conceptualmente como en apariencia, lo que probablemente explica por qué están cerca uno del otro en la tabla de precedencia. Quizás uno podría incluso argumentar que sería confuso &ser más alto que ==, pero aún así &&ser más bajo ==.

Una vez que se estableció un precedente de precedencia (!), Probablemente era mejor que otros idiomas lo siguieran por razones de coherencia.

Sin embargo, tiendo a estar de acuerdo con usted en que esto no es óptimo. En el uso real, los operadores de bits son más como operadores matemáticos que lógicos, y sería mejor si estuvieran agrupados con los operadores matemáticos con prioridad.


fuente