Hieronder volgt een tabel met de rangorde en associativiteit van alle operatoren in de talen C en C++ (als de operatoren ook bestaan in Java, Perl, PHP en vele andere recente talen, is de rangorde dezelfde als die gegeven is). De operatoren staan van boven naar beneden, in dalende volgorde. Afnemende voorrang verwijst naar de prioriteit van de groepering van operatoren en operanden. In een uitdrukking zal een operator die op een bepaalde rij staat, gegroepeerd worden vóór elke operator die op een rij eronder staat. Operatoren die in dezelfde cel staan (er kunnen meerdere rijen operatoren in een cel staan) worden gegroepeerd met dezelfde voorrang, in de gegeven richting. De voorrang van een operator wordt niet beïnvloed door overloading.
De syntaxis van uitdrukkingen in C en C++ wordt gespecificeerd door een zinsstructuur-grammatika. De hier gegeven tabel is afgeleid uit de grammatica. Voor de ISO C 1999-norm wordt in paragraaf 6.5.6 noot 71 gesteld dat de C-grammatika die door de specificatie wordt geleverd de rangorde van de C-operatoren definieert, en tevens dat de rangorde van operatoren die uit de grammatika voortvloeit nauw aansluit bij de volgorde van de secties in de specificatie:
“De syntaxis specificeert de rangorde van operatoren bij de evaluatie van een expressie, die dezelfde is als de volgorde van de belangrijkste subclausules van deze subclausule, hoogste rangorde eerst.”
Een voorrangstabel is weliswaar meestal adequaat, maar kan een paar details niet oplossen. Merk in het bijzonder op dat de ternaire operator elke willekeurige uitdrukking als middelste operand toestaat, ondanks het feit dat hij in de lijst een hogere rangorde heeft dan de toewijzings- en komma-operatoren. Dus a ? b, c : d
wordt geïnterpreteerd als a ? (b, c) : d
, en niet als de nietszeggende (a ? b), (c : d)
. Dus, de uitdrukking in het midden van de voorwaardelijke operator (tussen ?
en :
) wordt geparseerd alsof het haakjes zijn. Merk ook op dat het onmiddellijke, niet-parenthese resultaat van een C cast expressie niet de operand van sizeof
kan zijn. Daarom wordt sizeof (int) * x
geïnterpreteerd als (sizeof(int)) * x
en niet sizeof ((int) * x)
.
NotesEdit
De precedentietabel bepaalt de volgorde van binding in geketende expressies, wanneer deze niet expliciet wordt gespecificeerd door haakjes.
Voorrang en bindingen
Veel operatoren die reeksen met meerdere tekens bevatten, krijgen “namen” die zijn opgebouwd uit de operatienaam van elk teken. Bijvoorbeeld, +=
en -=
worden vaak plus gelijke(n) en min gelijke(n) genoemd, in plaats van het meer woordenloze “toewijzing door optellen” en “toewijzing door aftrekken”.De binding van operatoren in C en C++ wordt gespecificeerd (in de overeenkomstige standaarden) door een gefactoriseerde taalgrammatika, in plaats van een precedentietabel. Dit leidt tot een aantal subtiele conflicten. In C is de syntaxis voor een voorwaardelijke uitdrukking bijvoorbeeld:
logical-OR-expression ? expression : conditional-expression
terwijl dat in C++ is:
logical-OR-expression ? expression : assignment-expression
Dus de uitdrukking:
e = a < d ? a++ : a = d
wordt in de twee talen verschillend geparseerd. In C is deze expressie een syntaxisfout, omdat de syntaxis voor een toewijzingsexpressie in C is:
unary-expression '=' assignment-expression
In C++ wordt deze geparsed als:
e = (a < d ? a++ : (a = d))
wat een geldige expressie is.
int a = 1, b = 2, weirdVariable = (++a, b), d = 4;
Kritiek op de voorrang van bitwise- en gelijkwaardigheidsoperatoren
De voorrang van de bitwise logische operatoren is bekritiseerd. Conceptueel gezien zijn & en | rekenkundige operatoren zoals * en +.
Meer nog, in C++ (en latere versies van C) leveren gelijkheidsoperaties, met uitzondering van de drieweg vergelijkingsoperator, bool type waarden op die conceptueel een enkele bit zijn (1 of 0) en als zodanig niet goed thuishoren in “bitwise” operaties.
C++ operator synoniemenEdit
C++ definieert bepaalde sleutelwoorden om te fungeren als aliassen voor een aantal operatoren:
Keyword | Operator |
---|---|
en |
&& |
and_eq |
&= |
bitand |
& |
bitor |
| |
compl |
~ |
niet |
! |
not_eq |
!= |
or |
|| |
or_eq |
|= |
xor |
^ |
xor_eq |
^= |
Deze kunnen op precies dezelfde manier worden gebruikt als de interpunctiesymbolen die ze vervangen, aangezien het niet dezelfde operator onder een andere naam is, maar eerder eenvoudige tokenvervangingen voor de naam (tekenreeks) van de respectieve operator. Dit betekent dat de uitdrukkingen (een > 0 en niet vlag)
en (a >&& !vlag)
hebben identieke betekenissen. Het betekent ook dat, bijvoorbeeld, het bitand
sleutelwoord kan worden gebruikt om niet alleen de bitwise-en operator te vervangen, maar ook de address-of operator, en het kan zelfs worden gebruikt om referentietypes te specificeren (bijv. int bitand ref = n
). De ISO C specificatie laat deze sleutelwoorden toe als preprocessor macro’s in het header bestand iso646.h
. Voor compatibiliteit met C, voorziet C++ in de header ciso646
, waarvan het opnemen geen effect heeft.