2014-11-11 7 views
5

Ho appena visto il codice e non riesco a capire come la logica e si comporta con "cout" qui:Quale operazione logica AND esegue con lo streaming in uscita?

int userInput = 9; // Suppose user input is 9. 
int remainder = 9 % 2; 
(remainder & 1 && std::cout<<"odd")|| cout<<"even"; 
+0

non è necessaria la parentesi che è lì, ma a seconda della precedenza dell'operatore (non riesco a ricordarlo) potrebbe essere necessaria la parentesi intorno alla sotto-espressione 'remainder & 1'. –

+0

Vedere [C++ operator precedence] (http://en.cppreference.com/w/cpp/language/operator_precedence) –

risposta

6

La linea in questione:

(remainder & 1 && std::cout<<"odd") || cout<<"even"; 

è lo stesso di quanto segue al momento si prende precedenza degli operatori e overload dell'operatore in considerazione:

((remainder & 1) && (operator<<(std::cout, "odd").operator bool())) || (operator<<(std::cout, "even").operator bool()); 

std::cout (più genericamente, std::basic_ostream) ha gli operatori operator<<() e operator bool() definiti. Il primo operatore restituisce un riferimento std::basic_ostream&, ovvero un riferimento al flusso stesso (utile per concatenare le operazioni insieme). Il secondo operatore restituisce se il flusso si trova in uno stato di errore o meno.

vedere la seguente documentazione per maggiori dettagli:

C++ operator precedence

operator overloading

std::basic_ostream::operator<<

std::basic_ios::operator bool

+0

può fornire ulteriori dettagli o collegamenti a questo proposito. – Zubair

+0

@Zubair: collegamenti aggiunti. –

+0

Nitpick: il particolare 'operatore <<' invocato qui [è una funzione non membro] (http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt2). –

13

std::cout<<"odd" è un'espressione che restituirà std::cout (che è perché puoi fare std::cout << a << b << c). Quando viene valutato nel contesto booleano, restituisce semplicemente true se il bit di fail non è impostato. Quindi se l'operazione di output ha esito positivo, verrà valutata come vera.

Tuttavia, l'intento di questo codice non è di verificare che il valore, anzi è un intelligente (e non molto leggibile) modo per esprimere questo:

if (remainder & 1) { 
    std::cout << "odd"; 
} else { 
    std::cout << "even"; 
} 

si avvale della corto circuito natura degli operatori && e ||:

  • In a && b, se a è falsa, allora valutata come a(b non viene valutato!) altrimenti viene valutato come b.
  • In a || b, se a è vero allora si valuta come a(b non viene analizzato!) altrimenti viene valutata come b.

Quindi se remainder & 1 viene valutata come falsa (zero in questo caso), allora std::cout << "odd" non viene valutata perché le && espressione cortocircuiti, restituito false. Questo è l'operando di sinistra per l'espressione esterna ||, che causa la valutazione dello b (std::cout << "even"), scrivendo "pari" sull'output.

Se remainder & 1 viene valutato come vero (non zero in questo caso), viene valutato l'operando destro per &&, visualizzando "dispari". Supponendo che questa operazione abbia esito positivo, l'operando di sinistra per l'operazione || sarà true, il che provoca un cortocircuito e non valuta l'operando corretto.


I programmatori esperti sono in grado di conoscere esattamente che cosa sta succedendo qui, ma come avete trovato questa tecnica non è il più leggibile. È meglio (IMO) essere chiari sull'intento del codice, quindi utilizzerei solo un condizionale if o, per lo meno, utilizzare l'operatore ternario: std::cout << (remainder & 1 ? "odd" : "even").

In altre lingue (mi viene in mente JavaScript) (ab) utilizzare gli operatori di cortocircuito è una tecnica molto comune. Di solito non li vedo usati in questo modo in C++ e sconsiglio vivamente questo uso.

+0

Che funziona solo se il compilatore implementa un'espressione booleana short-curcuiting per saltare 'std :: cout <<" dispari "' se 'remainder & 1' restituisce false. Senza un short-curcuit, sia "cout <<" odd "' che 'cout <<" even "' verrebbero probabilmente valutati. –

+6

@RemyLebeau Se il compilatore non implementa il cortocircuito booleano, [non è un compilatore C++ conforme] (http://stackoverflow.com/questions/628526/is-short-circuiting-boolean-operators-mandated-in -CC-e-valutazione-ordine). – cdhowie

+0

@cdhowie: la tua spiegazione è più valida. – Zubair

Problemi correlati