2009-07-04 14 views
44

Ho letto da qualche parte che l'operatore ?: in C è leggermente diverso in C++, che esiste un codice sorgente che funziona in modo diverso in entrambe le lingue. Sfortunatamente, non riesco a trovare il testo da nessuna parte. Qualcuno sa cos'è questa differenza?Differenze di operatore condizionale tra C e C++

risposta

67

L'operatore condizionale in C++ può restituire un lvalue, mentre C non consente funzionalità simili.Quindi, il seguente è legale in C++:

(true ? a : b) = 1; 

di replicare questo in C, si dovrebbe ricorrere a if/else, o trattare con riferimenti direttamente:

*(true ? &a : &b) = 1; 

anche in C++, ?: e = operatori hanno equal precedence and group right-to-left, in modo tale che:

(true ? a = 1 : b = 2); 

è codice valido C++, ma genera un errore in C senza parentesi intorno all'ultima e xpression:

(true ? a = 1 : (b = 2)); 
+19

In C puoi scrivere * (true? & A: & b) = 1 invece – finnw

+0

@finnw: utile. aggiornato la mia risposta di conseguenza. – goldPseudo

+5

La seconda differenza non riguarda l'ordine delle operazioni, riguarda la precedenza degli operatori. – Barmar

22

La principale differenza pratica è che in C, la valutazione di?: Non può mai risultare in un valore l dove, come nel C++, può.

Ci sono altre differenze nella sua definizione che hanno poche conseguenze pratiche. In C++ il primo operando viene convertito in un bool, in C viene confrontato con 0. Questo è analogo alla differenza nella definizione di ==,! =, Ecc. Tra C e C++.

Esistono anche regole più complesse in C++ per dedurre il tipo di un'espressione?: Basata sui tipi degli operandi 2a e 3a. Ciò riflette la possibilità di conversioni implicite definite dall'utente in C++.

Codice di esempio. C++ valido; non valida C.

extern int h(int p, int q); 

int g(int x) 
{ 
     int a = 3, b = 5; 

     (x ? a : b) = 7; 

     return h(a, b); 
} 

gcc genera l'errore: "Errore: lvalue non valida in assegnazione" durante la compilazione di C, ma il codice viene compilato senza errori durante la compilazione di C++.

Edit: Sebbene: non può restituire un l-value in C, forse sorprendentemente la grammatica Per:? È:

conditional-expression: 
    logical-OR-expression 
    logical-OR-expression ? expression : conditional-expression 

Ciò significa che a ? b : c = d analizza come (a ? b : c) = d anche se (a causa alla regola 'not an l-value' questo non può dare come risultato un'espressione valida.

C++ cambia la grammatica di questo:

conditional-expression: 
    logical-or-expression 
    logical-or-expression ? expression : assignment-expression 

Mentre l'estensione per consentire condizionale-espressione sia un l-value in alcune situazioni avrebbe fatto a ? b : c = d valida senza la modifica grammatica, i nuovi mezzi di cambiamento grammatica che l'espressione è ora valida ma con il diverso significato di a ? b : (c = d).

Anche se non ho alcuna prova per esso, la mia supposizione che come il cambiamento grammatica non potrebbe rompere la compatibilità con il codice C esistente, era più probabile che la nuova grammatica produrrebbe un minor numero di sorprese con espressioni come:

make_zero ? z = 0 : z = 1; 
+0

La parte della risposta che descrive C parsing non è corretta. Nella grammatica C il LHS dell'operatore '=' non può contenere un operatore '?:' Non parentesi. L'analisi suggerita '(a? B: c) = d' non è realmente possibile. Nella grammatica C 'a? b: c = d' espressione non è affatto analizzabile. Qualsiasi compilatore che lo interpreti come '(a? B: c) = d' lo fa a proprio rischio. (Questo è tipicamente il caso dei compilatori ibridi C/C++ che tentano di unificare grammatiche C e C++ sotto il cofano.) Formalmente, non c'è alcun problema in esso, poiché il codice non valido è ancora rifiutato. Ma il messaggio "non un lvalue" è fuorviante. – AnT

+0

In C, 'a? b: c = d' è semplicemente una parola sintattica, una sequenza non analizzabile di token. Non è un'espressione. Affermare che assegna a un non-lvalue non è corretto, in quanto non vi è alcun "assegnamento" qui. – AnT

Problemi correlati