In de C-taal is de volgorde van berekening van functieargumenten niet gedefinieerd door de standaard (tot en met C99). Argumenten kunnen van links naar rechts, van rechts naar links of in een andere volgorde worden berekend (afhankelijk van de compiler of architectuur).
void fn(int a, int b) { /* ... */ } int x = 1; fn(x++, x++); // de volgorde van berekening van x++ en x++ is niet gedefinieerd!
"In welke volgorde worden functieargumenten in C berekend en kan ik op dit gedrag vertrouwen bij het schrijven van code?"
Een veelgemaakte fout is om te denken dat argumenten van links naar rechts worden berekend (in overeenstemming met expressies). In de praktijk wordt elke functieverzoek gecompileerd op basis van de keuze van de compiler (en platform).
void foo(int a, int b, int c); int x = 1; foo(x++, x++, x++); // het resultaat hangt af van de volgorde van berekening van de argumenten
Het echte antwoord: je kunt er niet op vertrouwen — het gedrag is niet gedefinieerd!
Verhaal
In een multi-platform product schreef een programmeur
push(stack, stack->size++, data);. Op de meeste platformen werkte alles, maar op één platform werd de grootte van de stack vergroot vóór het doorgeven van gegevens, en op een ander platform daarna. Gegevens werden "verloren" of niet correct geadresseerd, de fout trad zelden op en was erg moeilijk te debuggen.
Verhaal
In de netwerkprotocolbibliotheek werd de loggingfunctie aangeroepen met expressies-argumenten, die statistische tellers incrementeerden. De statistische rapporten werden onjuist gegenereerd: bij verschillende klanten verschilden de indices van de tellers, omdat ze niet in de verwachte volgorde werden uitgevoerd.
Verhaal
In de hardwarebedieningsinterface gaf de initialisatiefunctie pointers en verschuivingen door met incrementele waarden binnen de argumenten (type
init(ptr++, cnt++);). Op sommige processors werd de hardware correct geïnitieerd, terwijl er op andere een fout optrad, de oorzaak werd lange tijd in de hardware gezocht, terwijl het probleem in de onjuiste C-code lag.