Następująca tabela zawiera listę pierwszeństwa i asocjatywności wszystkich operatorów w językach C i C++ (jeśli operatory występują również w Javie, Perlu, PHP i wielu innych najnowszych językach, pierwszeństwo jest takie samo jak podane). Operatory są wymienione od góry do dołu, w malejącym pierwszeństwie. Pierwszeństwo malejące odnosi się do priorytetu grupowania operatorów i operandów. Biorąc pod uwagę wyrażenie, operator, który jest wymieniony w pewnym wierszu, będzie zgrupowany przed operatorem, który jest wymieniony w wierszu poniżej. Operatory, które znajdują się w tej samej komórce (w komórce może być kilka rzędów operatorów) są grupowane z tym samym pierwszeństwem, w danym kierunku. Na pierwszeństwo operatora nie ma wpływu przeciążanie.
Składnia wyrażeń w C i C++ jest określona przez gramatykę struktur frazowych. Podana tutaj tabela została wywnioskowana z tej gramatyki. Dla standardu ISO C 1999, sekcja 6.5.6 uwaga 71 stwierdza, że gramatyka C dostarczona przez specyfikację definiuje pierwszeństwo operatorów C, a także stwierdza, że pierwszeństwo operatorów wynikające z gramatyki ściśle odpowiada kolejności sekcji specyfikacji:
„Składnia określa pierwszeństwo operatorów w ocenie wyrażenia, które jest takie samo jak kolejność głównych podrozdziałów tego podrozdziału, najwyższe pierwszeństwo.”
Tablica pierwszeństwa, choć w większości wystarczająca, nie może rozwiązać kilku szczegółów. W szczególności zauważ, że operator trójskładnikowy pozwala na dowolne dowolne wyrażenie jako jego środkowy operand, mimo że jest wymieniony jako mający wyższe pierwszeństwo niż operatorzy przypisania i przecinka. Tak więc a ? b, c : d
jest interpretowany jako a ? (b, c) : d
, a nie jako bezsensowny (a ? b), (c : d)
. Tak więc, wyrażenie w środku operatora warunkowego (pomiędzy ?
a :
) jest parsowane tak, jakby było nawiasem. Zauważ również, że natychmiastowy, nienarodzicielski wynik wyrażenia rzutowania w C nie może być operandem sizeof
. Dlatego sizeof (int) * x
jest interpretowany jako (sizeof(int)) * x
, a nie sizeof ((int) * x)
.
NotesEdit
Tablica pierwszeństwa określa kolejność wiązania w wyrażeniach łańcuchowych, gdy nie jest ona wyraźnie określona przez nawiasy.
Precedencja i wiązania
Wiele operatorów zawierających sekwencje wieloznakowe otrzymuje „nazwy” zbudowane z nazwy operatora każdego znaku. Na przykład +=
i -=
są często nazywane plus equal(s) i minus equal(s), zamiast bardziej dosłownych „przypisanie przez dodanie” i „przypisanie przez odjęcie”.Wiązanie operatorów w C i C ++ jest określone (w odpowiednich Standardach) przez faktorowaną gramatykę językową, a nie tabelę pierwszeństwa. To tworzy pewne subtelne konflikty. Na przykład, w C, składnia wyrażenia warunkowego to:
logical-OR-expression ? expression : conditional-expression
podczas gdy w C++ jest to:
logical-OR-expression ? expression : assignment-expression
Więc, wyrażenie:
e = a < d ? a++ : a = d
jest parsowane inaczej w obu językach. W języku C wyrażenie to jest błędem składniowym, ponieważ składnia wyrażenia przypisania w C to:
unary-expression '=' assignment-expression
W języku C++ jest ono parsowane jako:
e = (a < d ? a++ : (a = d))
co jest poprawnym wyrażeniem.
int a = 1, b = 2, weirdVariable = (++a, b), d = 4;
Krytyka pierwszeństwa operatorów bitowych i równościEdit
Pierwszeństwo bitowych operatorów logicznych zostało skrytykowane. Konceptualnie, & i | są operatorami arytmetycznymi jak * i +.
Co więcej, w C++ (i późniejszych wersjach C) operacje równości, z wyjątkiem operatora porównania trójstronnego, dają wartości typu bool, które są konceptualnie pojedynczym bitem (1 lub 0) i jako takie nie należą do operacji „bitowych”.
Synonimy operatorów C++
C++ definiuje pewne słowa kluczowe, które działają jako aliasy dla wielu operatorów:
Słowo kluczowe | Operator |
---|---|
and |
&& |
and_eq |
&= |
bitand |
& |
bitor |
| |
compl |
~ |
not |
! |
not_eq |
!= |
or |
|| |
or_eq |
|= |
xor |
^ |
xor_eq |
^= |
Można ich używać dokładnie w taki sam sposób, jak symboli interpunkcyjnych, które zastępują, ponieważ nie są one tym samym operatorem pod inną nazwą, lecz raczej prostymi zamiennikami tokenów dla nazwy (łańcucha znaków) odpowiedniego operatora. Oznacza to, że wyrażenia (a > 0 i nie flaga)
oraz (a >&& !flag)
mają identyczne znaczenie. Oznacza to również, że na przykład, słowo kluczowe bitand
może być użyte do zastąpienia nie tylko operatora bitwise-and, ale również operatora address-of, a nawet może być użyte do określenia typów referencyjnych (np. int bitand ref = n
). Specyfikacja ISO C uwzględnia te słowa kluczowe jako makra preprocesora w pliku nagłówkowym iso646.h
. Dla kompatybilności z C, C++ dostarcza nagłówek ciso646
, którego włączenie nie ma żadnego efektu.