Dlaczego operatory bitowe mają niższy priorytet niż porównania?

63

Czy ktoś mógłby wyjaśnić uzasadnienie, dlaczego w wielu najpopularniejszych językach (patrz uwaga poniżej) operatory porównania (==,! =, <,>, <=,> =) Mają wyższy priorytet niż operatory bitowe (&, |, ^ , ~)?

Nie sądzę, że kiedykolwiek spotkałem się z zastosowaniem, w którym ten priorytet byłby naturalny. Zawsze są takie rzeczy jak:

  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

Przypadki, w których użyłbym:

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

są prawie nieistniejące.

Jaka była motywacja projektantów języków do decydowania o takim priorytecie operatorów?


Na przykład wszystkie oprócz SQL w 12 najpopularniejszych językach są takie jak na liście Popularność języków programowania na langpop.com: C, Java, C ++, PHP, JavaScript, Python, C #, Perl, SQL, Ruby, Shell, Visual Basic.

SF.
źródło
16
błąd w oryginalnym projekcie w C
maniaku zapadkowym
7
@gnat, jaki jest sens tej skargi? OP nie powiedział „wszystkie”, tylko „kilka najpopularniejszych języków”. Zdecydowana większość przestrzega tej kolejności. W tej tabeli tylko jeden z 12 najlepszych (SQL) nie zawiera: langpop.com
3
@ dan1111 point ma oczywiście pomóc ankieterom lepiej zrozumieć zadane pytanie i zapewnić lepsze odpowiedzi. Widzisz, to nie jest miejsce dla gry w zgadywanie - lub, jak mówi strona trasy : „To nie jest forum dyskusyjne. Nie ma chit-chat”.
komara
7
@gnat, zgadzam się z twoją obawą dotyczącą zgadywania gier, ale nie sądzę, że to się kwalifikuje, gdy prawie każdy popularny język wykazuje opisane zachowanie.
5
@Dunk: Typowe podejście „przez przeczucie” to [arithmetics] [logic operator] [arithmetics]. Większość programistów nie tworzy bałaganu w nawiasach, takich jak if(((x+getLowX()) < getMinX) || ((x-getHighX())>getMaxX())))- większość przyjmuje pierwszeństwo arytmetyki przed logiką i pisze, if( ( x + getLowX() < getMinX ) || ( x - getHighX() > getMaxX() )) zakładając pierwszeństwo +powyżej <. Teraz intuicyjnie if( x ^ getMask() != PATTERN ) powinien zachowywać się tak samo, XOR jest operatorem arytmetycznym. Fakt, że jest interpretowany jako if( x ^ ( getMask() != PATTERN ) )całkowicie sprzeczny z intuicją.
SF.

Odpowiedzi:

72

Języki skopiowały to z C, a dla C Dennis Ritchie wyjaśnia, że początkowo w B (i być może wczesnym C) istniała tylko jedna forma, &która w zależności od kontekstu działała nieco lub logicznie. Później każda funkcja ma swojego operatora: &dla bitowego i &&dla logicznego. Potem kontynuuje

Ich spóźnione wprowadzenie wyjaśnia niewierność reguł pierwszeństwa C. W B pisze się

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

sprawdzić, czy ajest równe bi cjest niezerowe; w takim wyrażeniu warunkowym lepiej jest &mieć niższy priorytet niż ==. W konwersji z B do C chce zastąpić &przez &&tak instrukcji; aby konwersja była mniej bolesna, postanowiliśmy zachować pierwszeństwo &operatora względem tego samego ==i po prostu oddzielić &&nieco priorytet &. Dziś wydaje się, że byłoby korzystne, aby przejść względne precedensami na &i ==, a tym samym uprościć wspólną C idiom: przetestować zamaskowaną wartość przed inną wartość, trzeba napisać

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

gdzie wewnętrzne nawiasy są wymagane, ale łatwo je zapomnieć.

AProgrammer
źródło
1
Czy to nie zawiódłoby, gdyby c=2Lub a==bskutkowało, ~0a nie 1?
SF.
Wydaje się, że a == b zwraca 0 lub 1, patrz cm.bell-labs.com/cm/cs/who/dmr/kbman.html .
AProgrammer
Sprawdź odniesienie w odpowiedzi i przeczytaj poprzedni tekst.
SShaheen,
1
@MasonWheeler: Zwłaszcza w systemach wbudowanych czasami konieczne jest użycie makr funkcyjnych [w niektórych przypadkach mogą one oferować wydajność rzędu rzędów wielkości lepszą niż funkcje wbudowane, aw niektórych systemach wbudowanych, które mogą być krytyczne]. Deklaracja zmiennych w takich makrach nie jest możliwa; użycie zmiennej globalnej w makrze może działać, ale wydaje się bardzo trudne.
supercat
6
@MasonWheeler: Czy możesz znaleźć Raspberry Pi lub Arduino za 0,50 USD w ilości 1000?
supercat
7

Operatory bitowe są powiązane z operatorami logicznymi zarówno koncepcyjnie, jak i pod względem wyglądu, co prawdopodobnie wyjaśnia, dlaczego są blisko siebie w tabeli pierwszeństwa. Być może można nawet argumentować, że byłoby mylące, ponieważ &być wyższym niż ==, ale &&być niższym wtedy ==.

Po ustaleniu precedensu precedensu (!) Prawdopodobnie dla lepszej spójności inne języki powinny go stosować.

Jednak zgadzam się z tobą, że nie jest to optymalne. W rzeczywistości operatory bitowe bardziej przypominają operatory matematyczne niż logiczne i byłoby lepiej, gdyby były zgrupowane z operatorami matematycznymi w pierwszej kolejności.


źródło