2013-05-17 16 views
7

I'v un codice seguente:è la precedenza dell'operatore ignorati 'se' condizioni

void main() 
{ 
    int k, x, y, z; 
    printf("\nExperiment 1:"); 
    x = 0, y = 0, z = 0; 
    k = x++ || y++ && z++; 
    printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k); 
    printf("\nExperiment 2:"); 
    x = 1, y = 0, z = 0; 
    k = x++ || y++ && z++; 
    printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k); 
} 

L'output:

Esperimento 1: x = 1, y = 1, z = 0 e k = 0

Esperimento 2: x = 2, y = 0, z = 0 ek = 1

Quello che ho capito è: per l'espressione sia vera, sia lato sinistro o lato destro di '||' deve essere diverso da zero. Inizia da sinistra. Se lasciato è diverso da zero, non valuta ulteriormente. Se è zero, parte dalla parte destra. A destra abbiamo '& &'. Quindi, partiamo nuovamente dal lato sinistro di & & e nel caso sia zero, l'espressione non può essere vera e non procede. In caso contrario, si valuta il lato destro del '& &'

La mia ipotesi era operatore & & ha precedenza maggiore. Quindi, entrambi i suoi argomenti avrebbero dovuto essere valutati e quindi & & avrebbe dovuto essere applicato su di esso seguito dalla valutazione di entrambi gli argomenti di ||.

Il compilatore si sta ottimizzando? Ho usato Visual Studio TC compatibile con Ottimizzazione disabilitato.

+5

Queste non sono "se le condizioni", a proposito. Sono semplicemente espressioni, utilizzando operatori booleani e operatori post-incremento. – unwind

+3

Solo perché && ha una precedenza più stretta non significa 'k = x ++ || (y ++ && z ++) 'eseguirà il && prima del ||. Questo è chiamato cortocircuito e molto noto. Ne dici anche tu stesso. Immagina: 'k = x ++ || f (& y, & z) 'dove f() restituisce' (* y) ++ && (* z) ++ '. È funzionalmente equivalente al tuo codice. – Matthias

+0

@ Matthias: in effetti; '++' ha una precedenza ancora maggiore di '&&'; non ci aspettiamo che il post-incremento avvenga prima di tutto solo a causa della precedenza ... – geoffspear

risposta

9

Penso che questo è coperto in C11 da §6.5.14 Logical OR operator (il corsivo è mio)

A differenza del bit a bit | operatore, il || operatore garantisce valutazione da sinistra a destra; se viene valutato il secondo operando, vi è un punto di sequenza tra le valutazioni del primo e del secondo operando di . Se il primo operando viene confrontato in modo non uguale a 0, il secondo operando non viene valutato.

4

Quindi l'espressione

k = x++ || y++ && z++; 

viene interpretato come (a causa di precendenza regole):

k = x++ || (y++ && z++); 

In experiement 1, abbiamo x = y = z = 0;.

In Experiement 2, abbiamo x = 1, y = z = 0;.

Quindi, l'espressione del lato destro si arresta dopo aver valutato y++, poiché il valore di tale valore è 0 e quindi il valore booleano e non può diventare vero.