Hierarchia i kolejność ocen

Pierwszeństwo i kojarzenie operatorów języka C wpływa na grupowanie i ocenę operandów w wyrażeniach. Pierwszeństwo operatora ma znaczenie tylko wtedy, gdy istnieją inne operatory o wyższym lub niższym pierwszeństwie. Wyrażenia z operatorami wyższego pierwszeństwa są najpierw oceniane. Pierwszeństwo można również opisać słowem "powiązanie". Operatory o wyższym pierwszeństwie mówi się, że mają ściślejsze powiązanie.

Poniższa tabela zawiera podsumowanie pierwszeństwa i kojarzenia (kolejności, w której oceniane są operandy) operatorów języka C, wymieniając je w kolejności pierwszeństwa od najwyższego do najniższego. Gdy kilka operatorów pojawia się razem, mają równe pierwszeństwo i są oceniane zgodnie z ich skojarzeniem. Operatory w tabeli są opisane w sekcjach rozpoczynających się od operatorów postfiksów. W pozostałej części tej sekcji przedstawiono ogólne informacje o pierwszeństwie i skojarzeniu.

Pierwszeństwo i skojarzenie operatorów języka C

Symbol 1 Typ operacji Łączność
[ ] ( ) . ->
++-- (postfix)
Wyrażenie Od lewej do prawej
sizeof & * + - ~ !
++-- (prefiks)
Jednoargumentowy Od prawej do lewej
typecasts Jednoargumentowy Od prawej do lewej
* / % Mnożenie Od lewej do prawej
+ - Dodawanie Od lewej do prawej
<< >> Przesunięcie bitowe Od lewej do prawej
< > <= >= Relacyjne Od lewej do prawej
== != Równość Od lewej do prawej
& Bitowe i Od lewej do prawej
^ Bitowe wykluczanie lub Od lewej do prawej
| Bitowe inkluzywne or Od lewej do prawej
&& Logiczne I Od lewej do prawej
|| Logiczne OR Od lewej do prawej
? : Wyrażenie warunkowe Od prawej do lewej
= *= /= %=
+= -= <<= >>= &=
^= |=
Proste i złożone przypisanie 2 Od prawej do lewej
, Ocena sekwencka Od lewej do prawej

1 Operatory są wymienione w kolejności malejącej pierwszeństwa. Jeśli kilka operatorów pojawia się w tym samym wierszu lub w grupie, mają równe pierwszeństwo.

2 Wszystkie proste i złożone operatory przypisania mają równe pierwszeństwo.

Wyrażenie może zawierać kilka operatorów o równym pierwszeństwie. Gdy kilka takich operatorów pojawia się na tym samym poziomie w wyrażeniu, ocena jest kontynuowana zgodnie z skojarzeniem operatora , od prawej do lewej lub od lewej do prawej. Kierunek oceny nie ma wpływu na wyniki wyrażeń, które obejmują więcej niż jedną mnożenie (), dodanie (*+) lub operator binarno-bitowy (&, |lub ^) na tym samym poziomie. Kolejność operacji nie jest definiowana przez język. Kompilator jest bezpłatny do oceny takich wyrażeń w dowolnej kolejności, jeśli kompilator może zagwarantować spójny wynik.

Tylko sekwencyjne oceny (), logiczne i logiczne (,&&), logiczne or (), warunkowe wyrażenie (||? :) i operatory wywołań funkcji stanowią punkty sekwencji, a zatem gwarantują określoną kolejność oceny dla ich operandów. Operator wywołania funkcji jest zestawem nawiasów po identyfikatorze funkcji. Operator oceny sekwencyjnej (,) ma gwarancję oceny operandów od lewej do prawej. (Operator przecinka w wywołaniu funkcji nie jest taki sam jak operator oceny sekwencyjnej i nie zapewnia żadnej takiej gwarancji). Aby uzyskać więcej informacji, zobacz Punkty sekwencji.

Operatory logiczne gwarantują również ocenę swoich operandów od lewej do prawej. Oceniają jednak najmniejszą liczbę operandów potrzebnych do określenia wyniku wyrażenia. Jest to nazywane oceną "zwarciową". W związku z tym niektóre operandy wyrażenia mogą nie być oceniane. Na przykład w wyrażeniu

x && y++

drugi operand, , jest oceniany tylko wtedy, y++gdy x ma wartość true (nonzero). W związku z tym nie jest zwiększany, y jeśli x jest to fałsz (0).

Przykłady

Na poniższej liście przedstawiono sposób automatycznego powiązania kompilatora z kilkoma przykładowymi wyrażeniami:

Wyrażenie Automatyczne powiązanie
a & b || c (a & b) || c
a = b || c a = (b || c)
q && r || s-- (q && r) || s--

W pierwszym wyrażeniu operator bitowo-AND (&) ma wyższy priorytet niż operator logiczny OR (||), więc a & b tworzy pierwszy operand operacji logicznej OR.

W drugim wyrażeniu operator logiczny OR (||) ma wyższy priorytet niż operator prostego przypisania (=), więc b || c jest pogrupowany jako operand po prawej stronie w przypisaniu. Należy pamiętać, że wartość przypisana do a wartości to 0 lub 1.

Trzecie wyrażenie pokazuje poprawnie sformułowane wyrażenie, które może spowodować nieoczekiwany wynik. Operator logiczny AND (&&) ma wyższy priorytet niż operator logiczny OR (||), więc q && r jest grupowany jako operand. Ponieważ operatory logiczne gwarantują ocenę operandów od lewej do prawej, q && r jest obliczana przed s--. q && r Jeśli jednak zostanie obliczona wartość niezerowa, s-- nie zostanie obliczona i s nie zostanie zdekrementowana. Jeśli nie dekrementacja s spowoduje problem w programie, s-- powinien pojawić się jako pierwszy operand wyrażenia lub s powinien zostać zdekrementowany w oddzielnej operacji.

Następujące wyrażenie jest nielegalne 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 jest pogrupowany jako operand. Operator wyrażenia warunkowego (? :) ma najwyższy priorytet. Jego pierwszy operand to p == 0, a drugi operand to p += 1. Jednak ostatni operand operatora wyrażenia warunkowego jest uważany za p zamiast p += 2, ponieważ to wystąpienie p powiązania ściślej z operatorem wyrażeń warunkowych niż do operatora przypisania złożonego. Występuje błąd składniowy, ponieważ += 2 nie ma operandu po lewej stronie. Należy użyć nawiasów, aby zapobiec błędom tego rodzaju i wygenerować bardziej czytelny kod. Na przykład można użyć nawiasów, jak pokazano poniżej, aby poprawić i wyjaśnić poprzedni przykład:

( p == 0 ) ? ( p += 1 ) : ( p += 2 )

Zobacz też

Operatory języka C