Udostępnij za pośrednictwem


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ć wyrazem "binding". Mówi się, że operatory o wyższym priorytecie mają mocniejsze powiązanie.

W poniższej tabeli podsumowano pierwszeństwo i kojarzenie (kolejność oceniania operandów) operatorów języka C, wyświetlając je w kolejności 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. Pozostała część tej sekcji zawiera ogólne informacje o pierwszeństwie i skojarzeniu.

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

Symbol 1 Typ operacji Łączność
[ ] ( ) . ->
++-- (postfiks)
Wyrażenie Od lewej do prawej
sizeof & * + - ~ !
++-- (prefiks)
Jednoargumentowy Od prawej do lewej
typecasts Jednoargumentowy Od prawej do lewej
* / % Multiplikatywne Od lewej do prawej
+ - Dodatek 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
^ Bitowo-wyłączny-OR 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 jest wyświetlanych 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ż jedno mnożenie (*), dodanie (+) lub operator binarny bitowy (&, |lub ^) na tym samym poziomie. Kolejność operacji nie jest definiowana przez język. Kompilator jest wolny do oceny takich wyrażeń w dowolnej kolejności, jeśli kompilator może zagwarantować spójny wynik.

Tylko sekwencyjne obliczanie (,), logiczne AND (&&), logiczne OR (||), wyrażenie-warunkowe (? :) 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ę 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 obliczany tylko wtedy, y++gdy x ma wartość true (nonzero). W związku z tym nie jest zwiększany, y jeśli x wartość to false (0).

Przykłady

Poniższa lista pokazuje, 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 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 (=), dlatego b || c jest grupowany jako operand prawy w przypisaniu. Należy pamiętać a , że przypisana wartość 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 (||), dlatego q && r jest pogrupowany jako operand. Ponieważ operatory logiczne gwarantują ocenę operandów od lewej do prawej, q && r jest obliczana przed s--. Jeśli jednak q && r jest obliczana wartość niezerowa, s-- nie jest obliczana i s nie jest dekrementowana. Jeśli nie spowoduje to dekrementacji s , problem w programie s-- powinien pojawić się jako pierwszy operand wyrażenia lub s powinien zostać zdekrementowany w osobnej 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 następny 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 jest bardziej powiązane z operatorem wyrażenia warunkowego niż z operatorem 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ć powyższy przykład:

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

Zobacz też

Operatory języka C