
Undefiniertes Verhalten in C, Objective C und C++
Problem: Was ist das Ergebnis von i = ++i + i++?
Es ist alles möglich: Der Standard stellt keine Anforderungen. Möglicherweise kompiliert das Programm nicht, wird falsch ausgeführt (stürzt ab oder erzeugt unbemerkt falsche Ergebnisse) oder es tut vielleicht genau das, was der Programmierer möchte. Das genaue Verhalten ist undefiniert!
Das resultierende Verhalten hängt nicht nur von der spezifischen Hardware, Plattform und dem Compiler ab, sondern auch von den spezifischen Einstellungen (Optimierungsstufe, Debug- / Releaseversion) desselben Compilers. Dies führt zu nicht portierbarem Code und Fehlern, die schwer zu erkennen sind.
Lösung
Um undefiniertes Verhalten zu beseitigen, sollte man das Konzept des Sequenzpunkts verstehen. Der Standard in C definiert je einen Sequenzpunkt
- am Ende jedes vollen Ausdrucks (typischerweise am Semikolon ; )
- nach der Auswertung aller Funktionsargumente und vor der Ausführung des Funktionskörpers
- nach der Auswertung des Ausdrucks a und unter Nutzung des eingebauten (nicht überladenen) Operatoren
a && b
a || b
a? b : c
a , b
Es gibt zwei Hauptfälle mit undefiniertem Verhalten zwischen zwei Sequenzpunkten
i = i++ + 1; // undefined behavior
i = ++i + 1; // undefined behavior (well-defined in C++11)
++++i; // undefined behavior (well-defined in C++11)
f(++i, ++i); // undefined behavior
f(i = -1, i = -1); // undefined behavior
cout << i << i++; // undefined behavior
a[i] = i++; // undefined behavior
Weitere Aspekte
- Compiler-Warnungen aktivieren und ernst nehmen
- Verwendung statischer Analysetools (wie Clang, cppcheck usw.), um noch mehr Warnungen zu erhalten
Autor
Andreas Maier, Software Architect, Business Division Banking & Insurance
Zum Toilet Paper #56: Undefiniertes Verhalten in C, Objective C und C++ (pdf)