2016-02-26 21 views
17
int x = 5,y = 10; 
bool boolean = 0; 
int k = (boolean ? ++x, ++y : --x, --y); 
cout<<k; 

Quando booleana è 0, emette 9, tuttavia quando si tratta di 1 emette 10.I sa questo sta accadendo a causa di precedenza, ma non può esattamente a capire come sta accadendo, per favore aiutatemi a capire questo.Come viene eseguita questa espressione condizionale ternaria?

NOTA: So che posso ottenere l'output previsto se utilizzo la parentesi, o meglio scrivere un codice pulito, sto solo usando questo per capire come il compilatore valuterà espressioni come queste in base alla precedenza.

+0

è meglio usare 'true' e' false' con booleano – Garf365

+4

Letture su _comma operator_ e prefisso decremento di incremento. –

+1

E quale risultato ti aspetteresti? –

risposta

40

, ha precedenza inferiore a ?:. Il che significa che il parenthesising completo è:

int k = ((boolean ? (++x, ++y) : --x), --y); 

Come si può vedere, k è sempre inizializzato al valore di --y. È solo che se boolean è true, ++y si verifica prima.


Quando cercando la forma parentesi piena di espressione, pensare ad esso come costruire l'albero di espressione (in cui l'operatore più basso la precedenza è alla radice).

Trova l'operatore con la precedenza più bassa in un'espressione e parentesi il suo argomento sul lato sinistro e il suo argomento sul lato destro. Ripeti ricorsivamente all'interno delle sottoespressioni appena parentesi.

+0

Grazie, la tua risposta mi ha aiutato, puoi dirmi i passaggi per la parentesi di una particolare espressione data la precedenza, non sono in grado di decidere quali gruppi di parentesi per espressioni come questa. –

+0

@KaranJoisher Ho provato ad espandere la risposta di conseguenza. – Angew

+1

@KaranJoisher Perché non inserire semplicemente i paren per rimuovere tutte le ambiguità: 'int k = (booleano? (++ x, ++ y): (--x, --y));' Rende immediatamente ovvio quanto a quali parti vanno dove Non c'è bisogno di cercare di capire la precedenza degli operatori. –

22

causa l'operatore virgola con il più basso operator precedence, la sua dichiarazione è in realtà pari a

k = (boolean ? (++x, ++y) : --x), --y; 

Questo significa che quando boolean è true entrambi aumentare e diminuire y. Il risultato dell'espressione ternaria viene buttato via in entrambi i casi e k viene assegnato solo il risultato di --y.

Si noti che questo comportamento non è indefinito, poiché l'operatore virgola introduce un punto di sequenza.


Per ottenere il risultato che ci si aspetta, è necessario fare

k = boolean ? (++x, ++y) : (--x, --y); 

Nota che le parentesi intorno ++x, ++y è rigorosamente non necessaria, ma rende l'espressione più chiara.

+3

Mi stavo chiedendo se qualcuno stesse per parlare della non UBness del codice. Grazie per quello. – NathanOliver

+1

@NathanOliver Bene, è * il tipo di importante in casi come questo. :) –

+1

@NathanOliver Ti meriteresti UB per scrivere codice come questo. Non sono un compilatore, non voglio analizzare il codice. – edmz

8

Date le ottime risposte di cui sopra, si dovrebbe scrivere invece:

if (boolean) { 
    ++x; 
    ++y; 
} else { 
    --x; 
    --y;  
} 
int k = y; 

Perché allora il codice è più leggibile e chiara nel suo intento. Questo aiuterà chiunque debba mantenere il codice (incluso l'autore originale!) Senza che nessuno debba perdere tempo ponendo domande SO o preoccupandosi della precedenza di , o di ?: o quale sia la logistica di assegnazione a un'espressione così complessa.Qualsiasi compilatore moderno ottimizzerà sia questo che lo stesso allo stesso codice risultante

+6

Il post di OP è un uso intelligente del sequenziamento, ma anche il tipo di "intelligente" che ti farà odiare dai tuoi colleghi. – MtRoad

+1

sì, buon punto, finalmente. –

+0

Possono i down-voters spiegare perché? Mi mancano alcune opportunità cruciali di pre-ottimizzazione che è così importante che il mio codice non ha senso? Per favore dammi una buona ragione per scrivere un'inizializzazione come OP. O non come il mio. –

Problemi correlati