Storia della domanda:
Gli operatori logici && e || sono stati introdotti in C per controllare condizioni logiche complesse. La loro caratteristica è il supporto per la valutazione a corto circuito: il secondo operando non viene calcolato se il risultato può essere già determinato dal primo.
Problema:
Molti programmatori si aspettano che entrambi gli operandi vengano sempre calcolati, o usano in modo scorretto gli effetti collaterali nel secondo operando, supponendo che debba necessariamente essere eseguito. Nella pratica, questo porta a errori, perdite di risorse e comportamenti imprevisti.
Soluzione:
Comprendere il meccanismo della valutazione a corto circuito aiuta a costruire costrutti sicuri, specialmente nel controllo di puntatori, risorse e file. L'uso di effetti collaterali nella parte destra dell'espressione è accettabile solo se fatto consapevolmente. Esempio di controllo sicuro:
if (ptr && ptr->field) { /* ... */ }
Caratteristiche chiave:
Verrà eseguita l'espressione f() nel frammento: if (0 && f())
No, la funzione f() non verrà chiamata perché il risultato è già chiaro — l'espressione è falsa, calcolare ulteriormente è inutile.
E nel seguente caso: if (1 || f())?
Di nuovo, f() non verrà chiamata: il risultato è già vero dopo il primo operando.
Possono essere utilizzati gli operatori && e || per controllare l'ordine di esecuzione delle funzioni con effetti collaterali?
Tecnicamente sì, ma un tale controllo porta a codice illeggibile e instabile. È meglio esplicitare l'ordine delle chiamate delle funzioni, senza fare affidamento sul comportamento a corto circuito per gli effetti collaterali.
if (flag || process()) { // ... }
Il processo non verrà mai chiamato se flag è vero.
Vantaggi:
Svantaggi:
if (!flag) process();
Vantaggi:
Svantaggi: