Pourquoi les opérateurs au niveau des bits ont-ils une priorité plus basse que les comparaisons?

63

Quelqu'un pourrait-il expliquer pourquoi, dans la plupart des langages courants (voir la remarque ci-dessous), les opérateurs de comparaison (==,! =, <,>, <=,> =) Ont une priorité plus élevée que les opérateurs binaires (&, |, ^ , ~)?

Je ne pense pas avoir jamais rencontré un usage où cette préséance serait naturelle. C'est toujours du genre:

  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

Les cas où j'utiliserais:

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

sont presque inexistants.

Quelle était la motivation des concepteurs de langage pour décider de cette préséance des opérateurs?


Par exemple, tous les langages sauf le SQL dans les 12 langues les plus utilisées ressemblent à ceux de la liste de popularité du langage de programmation sur langpop.com: C, Java, C ++, PHP, JavaScript, Python, C #, Perl, SQL, Ruby, Shell, Visual Basic.

SF.
la source
16
erreur dans la conception originale de retour en C
freak freak
7
@gnat, quel est le but de cette plainte? Le PO n'a pas dit "tout", mais "un tas des langues les plus populaires". Et la grande majorité suit cet ordre. Dans ce tableau, un seul des 12 principaux (SQL) ne le fait pas: langpop.com
3
@ dan1111 vise naturellement à aider les répondants à mieux comprendre la question posée et à fournir de meilleures réponses. Vous voyez, ce n’est pas un endroit pour The Guessing Game - ou, comme le dit la page de la tournée , "Ce n’est pas un forum de discussion. Il n’ya pas de bavardage."
moucher le
7
@gnat, je partage votre inquiétude face aux jeux de devinettes, mais je ne pense pas que cela soit admissible lorsque presque tous les langages populaires présentent le comportement décrit.
5
@Dunk: L'approche commune "par intuition" est [arithmetics] [logic operator] [arithmetics]. La plupart des programmeurs ne créent pas un fouillis de parenthèses comme celui-ci if(((x+getLowX()) < getMinX) || ((x-getHighX())>getMaxX())))- la plupart présumeront que l'arithmétique prime sur la logique et écrivent en if( ( x + getLowX() < getMinX ) || ( x - getHighX() > getMaxX() )) supposant la priorité +ci - dessus <. Maintenant, intuitivement, il if( x ^ getMask() != PATTERN ) devrait se comporter de la même manière, XOR étant un opérateur arithmétique. Le fait que cela soit interprété comme if( x ^ ( getMask() != PATTERN ) )étant totalement contre-intuitif.
SF.

Réponses:

72

Les langues l’ont copié à partir de C, et pour C, Dennis Ritchie explique qu’au départ, en B (et peut-être au début C), il n’y avait qu’une forme &qui, en fonction du contexte, était un peu logique ou non. Plus tard, chaque fonction a son opérateur: &pour le bit à bit et &&pour le logique. Puis il continue

Leur introduction tardive explique l’influence des règles de priorité de C. En B on écrit

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

vérifier si aest égal à bet cest non nul; dans une telle expression conditionnelle, il est préférable d’ &avoir une priorité inférieure à celle de ==. En convertissant de B en C, on veut remplacer &par &&dans une telle déclaration; pour rendre la conversion moins pénible, nous avons décidé de conserver la priorité de l' &opérateur ==et de séparer &&légèrement la priorité de l' opérateur &. Aujourd’hui, il semble qu’il aurait été préférable de déplacer les priorités relatives de &et ==, simplifiant ainsi un langage C commun: pour comparer une valeur masquée à une autre, il faut écrire

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

où les parenthèses intérieures sont nécessaires mais facilement oubliées.

Programmateur
la source
1
Cela n'échouerait-il pas si c=2ou avait pour a==brésultat ~0et non 1?
SF.
Apparemment, a == b renvoie 0 ou 1, voir cm.bell-labs.com/cm/cs/who/dmr/kbman.html .
AProgrammer
Vérifiez la référence dans la réponse et lisez le texte précédent.
SShaheen
1
@MasonWheeler: Surtout dans les systèmes embarqués, il est parfois nécessaire d'utiliser des macros de type fonction (dans certains cas, elles peuvent offrir de meilleures performances que les fonctions en ligne, et dans certains systèmes embarqués, elles peuvent être critiques). La déclaration de variable dans de telles macros n'est pas possible; L'utilisation d'une variable globale dans une macro peut fonctionner, mais semble vraiment difficile.
Supercat
6
@MasonWheeler: Pouvez-vous trouver un Raspberry Pi ou un Arduino pour 0,50 USD en quantité 1000?
Supercat
7

Les opérateurs au niveau des bits sont liés aux opérateurs logiques à la fois conceptuellement et en apparence, ce qui explique probablement pourquoi ils sont proches les uns des autres dans le tableau des priorités. Peut-être pourrait-on même prétendre que ce serait déroutant &d’être plus élevé que d’ ==avoir &&été inférieur ==.

Une fois établi un précédent (!), Il était probablement préférable que les autres langues le suivent pour des raisons de cohérence.

Cependant, j'ai tendance à être d'accord avec vous pour dire que ce n'est pas optimal. En utilisation réelle, les opérateurs de bits s'apparentent davantage à des opérateurs mathématiques que des opérateurs logiques, et il serait préférable qu'ils soient groupés avec les opérateurs mathématiques en priorité.


la source