In der Programmiersprache C ist die Reihenfolge der Berechnung der Funktionsargumente nicht durch den Standard definiert (bis einschließlich C99). Die Argumente können von links nach rechts, von rechts nach links oder in jeder anderen Reihenfolge berechnet werden (nach Ermessen des Compilers oder der Architektur).
void fn(int a, int b) { /* ... */ } int x = 1; fn(x++, x++); // die Reihenfolge der Berechnung von x++ und x++ ist nicht definiert!
"In welcher Reihenfolge werden die Funktionsargumente in C berechnet und kann man sich darauf verlassen, wenn man Code schreibt?"
Ein häufiger Fehler ist zu glauben, dass die Argumente von links nach rechts berechnet werden (analog zu Ausdrücken). In der Praxis wird jeder Funktionsaufruf nach Ermessen des Compilers (und der Plattform) kompiliert.
void foo(int a, int b, int c); int x = 1; foo(x++, x++, x++); // das Ergebnis hängt von der Reihenfolge der Berechnung der Argumente ab
Die wirkliche Antwort: man kann sich nicht darauf verlassen — das Verhalten ist nicht definiert!
Geschichte
In einem plattformübergreifenden Produkt schrieb ein Programmierer
push(stack, stack->size++, data);. Auf den meisten Plattformen funktionierte alles, aber auf einer erhöhte sich die Stapelgröße vor der Datenübergabe, auf einer anderen danach. Daten wurden "verloren" oder falsch adressiert, der Fehler trat selten auf und war sehr schwierig zu debuggen.
Geschichte
In der Netzwerkprotokollbibliothek wurde die Protokollierungsfunktion mit Argumentausdrücken aufgerufen, die statistische Zähler erhöhten. Statistische Berichte wurden falsch generiert: Bei verschiedenen Kunden wichen die Zählerindizes ab, da sie nicht in der erwarteten Reihenfolge ausgeführt wurden.
Geschichte
In der Hardwaresteuerungsschnittstelle übergab die Initialisierungsfunktion Zeiger und Offsets mit Inkrement innerhalb der Argumente (z.B.
init(ptr++, cnt++);). Auf einigen Prozessoren wurde die Hardware korrekt initialisiert, auf anderen trat ein Fehler auf, die Ursache wurde lange in der Hardware gesucht, obwohl das Problem im fehlerhaften C-Code lag.