Achtergrond van de vraag
Operatorprioriteit is geïntroduceerd in C om de volgorde van berekeningen in wiskundige en logische uitdrukkingen te beheersen. Ondanks dat wiskundige operators een historisch verwachte prioriteit hebben (zoals in de algebra), heeft de opmars van veel nieuwe operators (logische, bitwise, toewijzing, enz.) de situatie gecompliceerd. Om de kans op fouten te verkleinen en de leesbaarheid te verbeteren, is er een officiële lijst van prioriteiten en associativiteit van operators ontstaan.
Probleem
Door het grotere aantal operators en hun verschillende aard (rekenkundige, vergelijkingen, toewijzingen, logische, indexering) ontstaan er ambiguïteiten bij het samenstellen van complexe uitdrukkingen. Een verkeerd begrip van de volgorde van toepassing leidt tot logische fouten en niet altijd voor de hand liggende bugs, vooral bij de combinatie van bitwise en logische operators, pointers, incrementen en de terniaire operator.
Oplossing
Voorbeeldcode:
#include <stdio.h> int main() { int a = 1, b = 2, c = 3, d; d = a + b * c; // b*c wordt eerder uitgevoerd: d = 1 + (2*3) = 7 printf("%d\n", d); d = a + b << 1; // a + b = 3, dan 3 << 1 (6) printf("%d\n", d); d = a < b ? a++ : b++; printf("%d\n", d); // a < b is waar => d = a (1), a wordt na verhoogd }
Belangrijke kenmerken:
Wat geeft de expressie x = y > z ? y : z; als je de haakjes vergeet?
Antwoord: De terniaire operator ?: heeft een lagere prioriteit dan >. Eerst wordt (y > z) berekend, waarna er tussen y en z wordt gekozen. Maar als je het combineert met toewijzing, kunnen er onverwachte effecten optreden. Het is beter om altijd haakjes te gebruiken: x = (y > z) ? y : z;.
*Wat geeft de expressie p++ en waarom?
Antwoord: De post-increment operator (++) heeft een hogere prioriteit dan dereferentie (*), dus *p++ wordt *(p++): eerst wordt p gebruikt en verhoogd, dan pas wordt er gedereferenceerd, wat kan verschillen van *++p (dereferentie na incrementeer).
Waarom werkt de expressie a & b == c niet zoals verwacht?
Antwoord: De operator == heeft een hogere prioriteit dan &, dus de expressie wordt geanalyseerd als a & (b == c), en niet als (a & b) == c, wat een onverwacht resultaat kan opleveren. Voor de gewenste logica moeten haakjes worden gebruikt.
if ((a & b) == c) { ... }
Negatieve case
Bij het optimaliseren van code heeft de programmeur verschillende operators zonder haakjes samengevoegd: if( mask & flag == 0 ) ..., met als gevolg dat de logica van de controle niet correct werkte en leidde tot een storing in het systeem.
Voordelen:
Nadelen:
Positieve case
Gebruik van expliciete groepering: if( (mask & flag) == 0 ) ..., de logica is transparant, gemakkelijk om vlaggen te wijzigen.
Voordelen:
Nadelen: