Hierarchia i kolejność ocen
Priorytet i łączność operatorów C wpływa na grupowanie i opracowanie argumentów w wyrażeniach.Priorytet operatora ma znaczenie tylko wtedy gdy istnieją inne operatory o mniejszym lub większym priorytecie.Wyrażenia zawierające operatory o wyższym priorytecie są opracowywane jako pierwsze.Priorytet można określić również mianem "wiązania". O operatorach o wyższym priorytecie mówi się, że mają ciaśniejsze wiązanie.
W następującej tabeli podsumowano priorytet i łączność (kolejność, w której opracowywane są operandy) operatorów C, wymieniając je w kolejności od najwyższego do najniższego.W przypadku gdy kilka operatorów pojawia się razem, mają równy priorytet i są opracowywane według ich łączności.Operatory w tabeli są opisane w sekcjach, począwszy od Operatory przyrostkowe.Pozostała część tej sekcji zawiera informacje ogólne na temat priorytetu i łączności.
Priorytet i łączność operatorów C
Symbol1 |
Typ operacji |
Łączność |
---|---|---|
[ ] ( ) . –> przyrostkowy ++ i przyrostkowy –– |
Wyrażenie |
Od lewej do prawej. |
przyrostkowy ++ i przyrostkowy–– sizeof & * + – ~ ! |
Jednoargumentowy |
Od prawej do lewej |
typecasts |
Jednoargumentowy |
Od prawej do lewej |
* / % |
Mnożący |
Od lewej do prawej. |
+ – |
Dodatek |
Od lewej do prawej. |
<< >> |
Przesunięcie bitowe |
Od lewej do prawej. |
< > <= >= |
Relacyjny |
Od lewej do prawej. |
== != |
Równość |
Od lewej do prawej. |
& |
Operator bitowy-AND |
Od lewej do prawej. |
^ |
Operator bitowy wyłączny OR |
Od lewej do prawej. |
| |
Operator bitowy włączny OR |
Od lewej do prawej. |
&& |
Logiczny AND |
Od lewej do prawej. |
|| |
Logiczny OR |
Od lewej do prawej. |
? : |
Wyrażenie warunkowe |
Od prawej do lewej |
= *= /= %= += –= <<= >>=&= ^= |= |
Proste i złożone assignment2 |
Od prawej do lewej |
, |
Opracowywanie sekwencyjne |
Od lewej do prawej. |
1.Operatory są przedstawione w kolejności malejącej według priorytetu.Jeżeli kilka operatorów pojawia się w tym samym wierszu lub w grupie, mają równy priorytet.
2.Wszystkie operatory prostego i złożonego przypisania mają równy priorytet.
Wyrażenie może zawierać kilka operatorów z równym priorytetem.Kiedy kilka takich operatorów pojawi się na tym samym poziomie w wyrażeniu, opracowywanie jest kontynuowane zgodnie z łącznością operatora, albo od prawej do lewej albo od lewej do prawej.Kierunek opracowywania nie wpływa na wynik wyrażeń, które zawierają więcej niż jeden operator mnożenia (*), dodawania (+), lub bitowej wartości logicznej (& | ^) na tym samym poziomie.Kolejność operacji nie jest zdefiniowana przez język.Kompilator jest bezpłatny do opracowywania wyrażeń w dowolnej kolejności, jeśli kompilator może zagwarantować spójne wyniki.
Tylko sekwencyjne opracowywanie (,), logiczne-AND (&&), logiczny OR (||), wyrażenie warunkowe (? :), i operatory wywołania funkcji stanowią punkty sekwencji i dlatego gwarantują określoną kolejność opracowywania ich argumentów.Operator wywołania funkcji jest zestawem nawiasów następującym po identyfikatorze funkcji.Operator sekwencyjnego opracowywania (,) gwarantuje sprawdzanie jego argumentów od lewej do prawej. (Należy zauważyć, że przecinek w wywołaniu funkcji to nie to samo co operator sekwencyjnego opracowywania i nie zapewnia takiej gwarancji). Aby uzyskać więcej informacji zobacz Punkty sekwencji.
Operatory logiczne również gwarantują opracowywanie ich argumentów od lewej do prawej.Jednakże opracowują najmniejszą liczbę argumentów potrzebnych do ustalenia wyniku wyrażenia.Jest to tak zwane "pomijanie warunków oceny".Tak więc niektóre argumenty wyrażenia mogą nie zostać opracowane.Na przykład w wyrażeniu
x && y++
Drugi operand y++ jest opracowywany tylko wtedy, gdy x ma wartość true (jest niezerowy).Tak więc y nie jest zwiększany, jeśli x ma wartość false (0).
Przykłady
Na poniższej liście przedstawiono, jak kompilator automatycznie wiąże kilka przykładowych wyrażeń:
Wyrażenie |
Automatyczne wiązanie |
---|---|
a & b || c |
(a & b) || c |
a = b || c |
a = (b || c) |
q && r || s-- |
(q && r) || s–– |
W pierwszym wyrażeniu bitowe AND (&) ma wyższy priorytet niż operator logiczny OR (||), więc a & b stanowi pierwszy argument operacji logicznej OR.
W drugim wyrażeniu, operator logiczny OR (||) ma wyższy priorytet niż operator prostego przypisania (=), więc b || c zostanie zgrupowane jako operand po prawej stronie w przypisaniu.Należy zauważyć, że wartość przypisywana do a jest równa 0 lub 1.
Trzecie wyrażenie zawiera poprawnie sformułowane wyrażenie, które może dać nieoczekiwane wyniki.Logiczny operator AND (&&) ma wyższy priorytet niż operator logiczny OR (||), więc q && r zostanie zgrupowane jako operand.Ponieważ operatory logiczne gwarantują opracowanie operandów od lewej do prawej, q && r będzie oceniane przed s––.Jednakże jeśli q && r da w wyniku wartość różną od zera, s–– nie jest opracowywane a s nie zostanie zmniejszone.Jeśli nie zmniejszenie s mogłoby spowodować problem w programie, s–– powinien pojawić się jako pierwszy argument wyrażenia, lub s powinno być zmniejszane w oddzielnej operacji.
Następujące wyrażenie jest niedozwolone i generuje komunikat diagnostyczny w czasie kompilacji:
Niedozwolone wyrażenie |
Domyślne grupowanie |
---|---|
p == 0 ? p += 1: p += 2 |
( p == 0 ? p += 1 : p ) += 2 |
W tym wyrażeniu, operator równości (==), ma najwyższy priorytet, więc p == 0 zostanie zgrupowane jako operand.Operator wyrażenia warunkowego (? :) ma następny najwyższy priorytet.Pierwszy operand to p == 0, a drugi to p += 1.Jednakże za ostatni operand wyrażenia warunkowego uważany jest p zamiast p += 2, od tego wystąpienia p ściślej wiąże się z operatorem wyrażenia warunkowego, niż z operatorem przypisania.Występuje błąd składni, ponieważ += 2 nie ma operandu po lewej stronie.Aby zapobiec wystąpieniu błędów tego rodzaju i stworzyć bardziej czytelny kod należy używać nawiasów.Na przykład można użyć nawiasów tak jak pokazano poniżej aby poprawić i wyjaśnić poprzedni przykład:
( p == 0 ) ? ( p += 1 ) : ( p += 2 )