Perché gli operatori bit a bit hanno una priorità inferiore rispetto ai confronti?


63

Qualcuno potrebbe spiegare la logica, perché in un gruppo di lingue più popolari (vedi nota sotto) gli operatori di confronto (==,! =, <,>, <=,> =) Hanno una priorità maggiore rispetto agli operatori bit a bit (&, |, ^ , ~)?

Non credo di aver mai incontrato un uso in cui questa precedenza sarebbe naturale. È sempre roba del tipo:

  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

I casi in cui userei:

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

sono quasi inesistenti.

Qual è stata la motivazione dei progettisti del linguaggio a decidere su tale precedenza degli operatori?


Ad esempio, tutti tranne SQL nelle prime 12 lingue sono simili a quelli nell'elenco di Popolarità del linguaggio di programmazione su langpop.com: C, Java, C ++, PHP, JavaScript, Python, C #, Perl, SQL, Ruby, Shell, Visual Basic.


16
errore nel design originale di nuovo in C
maniaco del cricchetto,

7
@gnat, qual è lo scopo di quella denuncia? L'OP non ha detto "tutto", solo "un mucchio delle lingue più popolari". E la stragrande maggioranza segue questo ordine. In questa tabella, solo uno dei 12 principali (SQL) no: langpop.com

3
Il punto @ dan1111 è, naturalmente, per aiutare i rispondenti a comprendere meglio la domanda posta e fornire risposte migliori. Vedi, questo non è un posto per The Guessing Game - o, come dice la pagina del tour , "Non è un forum di discussione. Non ci sono chit-chat".
moscerino

7
@gnat, sono d'accordo con la tua preoccupazione per indovinare i giochi, ma non credo che ciò si qualifichi quando quasi ogni lingua popolare mostra il comportamento descritto.

5
@Dunk: l'approccio comune "per intuizione" è [arithmetics] [logic operator] [arithmetics]. La maggior parte dei programmatori non crea un pasticcio di parentesi come if(((x+getLowX()) < getMinX) || ((x-getHighX())>getMaxX())))- la maggior parte assumerà la precedenza dell'aritmetica sulla logica e scriverà if( ( x + getLowX() < getMinX ) || ( x - getHighX() > getMaxX() )) assumendo la precedenza di cui +sopra <. Ora intuitivamente if( x ^ getMask() != PATTERN ) dovrebbe comportarsi allo stesso modo, XOR essendo un operatore aritmetico. Il fatto che sia interpretato come if( x ^ ( getMask() != PATTERN ) )completamente controintuitivo.
SF.

Risposte:


72

Le lingue lo hanno copiato da C, e per C, Dennis Ritchie spiega che inizialmente, in B (e forse all'inizio del C), esisteva solo una forma &che, a seconda del contesto, faceva un bit per bit o logico. Successivamente, ogni funzione ha ottenuto il suo operatore: &per quello bit per bit e &&per quello logico. Quindi continua

La loro tardiva introduzione spiega un'infelicità delle regole di precedenza di C. In B si scrive

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

per verificare se è auguale be cdiverso da zero; in una tale espressione condizionale è meglio che &abbiano una precedenza inferiore a ==. Nel convertire da B a C, si vuole sostituire &con &&una simile affermazione; per rendere la conversione meno dolorosa, abbiamo deciso di mantenere la precedenza &dell'operatore la stessa relativa ==e semplicemente dividere &&leggermente la precedenza di &. Oggi sembra che sarebbe stato preferibile spostare le relative precedenti di &e ==, e quindi semplificare un linguaggio C comune: per testare un valore mascherato rispetto a un altro valore, si deve scrivere

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

dove sono richieste le parentesi interne ma facilmente dimenticabili.


1
Non fallirebbe se c=2Or si a==btraducesse in ~0e no 1?
SF.

Sembra così, a == b restituisce 0 o 1, vedere cm.bell-labs.com/cm/cs/who/dmr/kbman.html .
AProgrammer

Controlla il riferimento nella risposta e leggi il testo precedente.
SShaheen,

1
@MasonWheeler: specialmente nei sistemi embedded, a volte è necessario utilizzare macro simili a funzioni [in alcuni casi, possono offrire ordini di grandezza migliori prestazioni rispetto alle funzioni in linea e in alcuni sistemi embedded che possono essere critici]. La dichiarazione di variabili all'interno di tali macro non è possibile; l'utilizzo di una variabile globale all'interno di una macro potrebbe funzionare, ma sembra davvero complicato.
supercat

6
@MasonWheeler: riesci a trovare un Raspberry Pi o Arduino per $ 0,50 in quantità 1000?
supercat

7

Gli operatori bit a bit sono correlati agli operatori logici sia concettualmente che apparentemente, il che probabilmente spiega perché sono vicini l'uno all'altro nella tabella delle precedenti. Forse si potrebbe anche sostenere che sarebbe confuso &essere più alti di ==, eppure &&essere più bassi di allora ==.

Una volta impostato un precedente (!), Probabilmente era meglio che altre lingue lo seguissero per motivi di coerenza.

Tuttavia, tendo a concordare con te sul fatto che ciò non è ottimale. Nell'uso effettivo, gli operatori di bit sono più simili agli operatori matematici che a quelli logici, e sarebbe meglio se fossero raggruppati con gli operatori matematici in precedenza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.