2012-03-13 6 views
6

Sappiamo tutti che l'operatore logico && cortocircuito se l'operando di sinistra è false, perché sappiamo che se un operando è false, il risultato è anche false.Perché il cortocircuito bit a bit e l'operatore non funzionano?

Perché l'operatore bit a bit & non è in cortocircuito? Se l'operando di sinistra è 0, allora sappiamo che il risultato è anche 0. Ogni lingua che ho provato in (C, Javascript, C#) valuta entrambi gli operandi invece di fermarsi dopo il primo.

C'è qualche motivo per cui sarebbe una cattiva idea lasciare che l'operatore & cortocircuito? In caso contrario, perché la maggior parte delle lingue non lo rendono cortocircuito? Sembra un'ovvia ottimizzazione.

+1

Un motivo potrebbe essere quello di consentire gli effetti collaterali delle chiamate di funzione. –

+3

Poiché gli operatori bit a bit vengono in genere utilizzati per, beh, operazioni bit a bit su operandi interi (e quelli generalmente corrispondono alle istruzioni di una singola macchina), si tratterà diversamente dall'ottimizzazione per introdurre un ulteriore condizionale per il controllo dei rari 0 casi. Perché la moltiplicazione non cortocircuita su 0? Bene, perché è una semplice operazione aritmetica che corrisponde ad una singola istruzione della macchina e verifica che nessuno controllerebbe mai ogni moltiplicazione per un operando 0. –

+0

L'operatore '|' bit a bit poteva cortocircuitare se l'operando di sinistra era '0xFFFFFFFF'. –

risposta

9

Direi che è perché un bit a bit and nella lingua di origine viene in genere convertito direttamente in un'istruzione bit and che deve essere eseguita dal processore. Questo, a sua volta, viene implementato come un gruppo del numero corretto di porte and nell'hardware.

Nella maggior parte dei casi non vedo questo come l'ottimizzazione di qualcosa. La valutazione del secondo operando normalmente costa meno del test per vedere se è necessario valutarlo.

+1

Sarebbe utile se il secondo operando implicasse un calcolo costoso. –

+3

@PeterOlson Sì, e solo nel raro caso l'operando di sinistra è 0. Ricorda che stiamo parlando di numeri interi qui e un valore intero di 0 è molto più raro di un valore booleano di 'false' (anche se forse più frequente di altri numeri). –

2

Le operazioni a bit sono di solito così economiche che il controllo renderebbe l'operazione due volte più lungo o più, mentre il guadagno derivante dal cortocircuito di un operatore logico è potenzialmente molto elevato.

2

Se il compilatore deve emettere un assegno per entrambi gli operandi di &, immagino che sarà molto più lento in qualsiasi condizione NORMALE.

7

Il cortocircuito non è un dispositivo di ottimizzazione. È un dispositivo di controllo del flusso. Se non si riesce a cortocircuitare p != NULL && *p != 0, non si otterrà un programma leggermente più lento, si otterrà un programma in crash.

Questo tipo di cortocircuito non ha quasi mai senso per gli operatori bit a bit, e è più costoso del normale operatore senza cortocircuito.

+1

Questo argomento mi sembra al contrario. Il cortocircuito può essere utilizzato come dispositivo di controllo del flusso * perché * esiste come ottimizzazione. Se '&&' non ha cortocircuito, codice come questo non sarebbe mai stato valido per scrivere; dovrebbe essere due test separati. Tuttavia, sono d'accordo sul fatto che il corto circuito bit a bit sarebbe sufficientemente raro in pratica che sarebbe probabilmente più costoso nel lungo periodo. Tutto dipende dalla probabilità di un valore 0 per l'operando di sinistra nel contesto del codice chiamante. –

+0

@QuinnTaylor L'ottimizzazione, per definizione, influisce solo sulle prestazioni e non sul significato. Tale codice ottiene writren perché è naturale scrivere codice come questo, e le alternative sono scomode. Se && non avesse cortocircuito, allora il linguaggio probabilmente si spegnerebbe e sarebbe stato sostituito da qualcosa che non era difficile da usare. –

1

Per lo stesso motivo che * non si interrompe se il primo operando è 0, sarebbe un caso speciale oscuro e l'aggiunta di test di runtime speciali per rendere tutti i multipli più lenti.

Quando gli operandi non sono costanti, il cortocircuito è più costoso del corto circuito, quindi non si vuole farlo a meno che il programmatore non lo richieda esplicitamente. Quindi vuoi veramente avere regole chiare e semplici su quando si verifica.