Historie der Frage:
Die logischen Operatoren && und || wurden in C eingeführt, um komplexe logische Bedingungen zu überprüfen. Eine Besonderheit ihrer Funktionsweise ist die Unterstützung der kurzen Bewertung: Der zweite Operand wird nicht ausgewertet, wenn das Ergebnis bereits nach dem ersten eindeutig bestimmt werden kann.
Problem:
Viele Programmierer erwarten, dass beide Operanden immer ausgewertet werden, oder nutzen Nebenwirkungen im zweiten Operanden falsch und nehmen an, dass er unbedingt ausgeführt wird. In der Praxis führt dies zu Fehlern, Ressourcenlecks und unerwartetem Verhalten.
Lösung:
Das Verständnis des Mechanismus der kurzen Bewertung hilft, sichere Konstruktionen zu erstellen, insbesondere bei Überprüfungen von Zeigern, Ressourcen und Dateien. Die Verwendung von Nebenwirkungen im rechten Teil des Ausdrucks ist nur absichtlich zulässig. Beispiel für eine sichere Überprüfung:
if (ptr && ptr->field) { /* ... */ }
Wesentliche Merkmale:
Wird der Ausdruck f() im Fragment ausgeführt: if (0 && f())?
Nein, die Funktion f() wird nicht aufgerufen, da das Ergebnis bereits klar ist — der Ausdruck ist falsch, eine weitere Auswertung ist nutzlos.
Und im nächsten Ausdruck: if (1 || f())?
Wieder wird f() nicht aufgerufen: Das Ergebnis ist bereits nach dem ersten Operand wahr.
Kann man die Operatoren && und || verwenden, um die Reihenfolge der Ausführung von Funktionen mit Nebenwirkungen zu steuern?
Technisch ist das möglich, aber solche Steuerungen führen zu unlesbarem und instabilem Code. Es ist besser, die Reihenfolge des Funktionsaufrufs ausdrücklich zu schreiben und sich nicht auf das Verhalten der kurzen Bewertung für Nebenwirkungen zu verlassen.
if (flag || process()) { // ... }
Der Prozess wird niemals aufgerufen, wenn flag wahr ist.
Vorteile:
Nachteile:
if (!flag) process();
Vorteile:
Nachteile: