2011-10-18 14 views
36

In 3.0.4 kernel di Linux, mm/filemap.c ha questa riga di codice:uso Bizzarro di operatore condizionale in Linux

retval = retval ?: desc.error; 

Ho provato la compilazione di un simile banco di prova minimo con gcc -Wall e non ricevere avvisi; il comportamento sembra identico a:

retval = retval ? retval : desc.error; 

Guardando lo standard C99, non riesco a capire che cosa descrive formalmente questo comportamento. Perché è OK?

+9

Dai un'occhiata a http://stackoverflow.com/questions/2806255/why-would-you-use-the-ternary-operator-without-assigning-a-value-for-the-true – vhallac

+3

Grazie, vhallac . Per quanto ne so, usare questa estensione GCC è una piccola scorciatoia che distrugge completamente la portabilità. –

+0

Esattamente quello che ho detto a un collega che ha cercato di usarlo su uno dei nostri progetti. :) – vhallac

risposta

35

Come molti altri hanno già detto, questa è un'estensione GCC, non parte di nessuno standard. Riceverai un avviso per questo se utilizzi lo switch -pedantic.

Il punto di questa estensione non è realmente visibile in questo caso, ma immaginate se invece era

retval = foo() ?: desc.error; 

Con l'estensione, foo() viene chiamato solo una volta. Senza di esso, è necessario introdurre una variabile temporanea per evitare di chiamare foo() due volte.

+13

ma retval = foo(); retval = retval? retval: desc.error; è MOLTO meglio ed è portatile al 100%. – akappa

+0

Mi è piaciuta molto anche la risposta di David Given, ma questo chiarisce la semantica della valutazione singola e mi dice di "-pedantic' che causa un avvertimento. Scelto. –

+1

@akappa: Non è meglio se preferisci evitare l'introduzione di variabili temporanee. Questa è una delle * estensioni * veramente vecchie di GCC, e riflette i gusti del linguaggio funzionale degli sviluppatori originali di GCC. Inoltre, al momento, tutte le dichiarazioni delle variabili locali dovevano essere in cima alla funzione; "dichiarazioni e codice misti" non era standard fino a C99. – zwol

3

Questa è un'estensione specifica di Gcc a C e non è standard.

7

Questa è un'estensione GCC denominata Conditionals with Omitted Operands. L'omissione dell'operando centrale ha l'effetto di utilizzare il valore del condizionale come operando omesso senza valutarlo di nuovo. È sicuro da usare anche se il condizionale è una macro.

19

È un'estensione gcc. x ?: y è equivalente a x ? x : y --- vedi http://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals.

Sì, penso che sia anche il male.

+0

Perché dici che è il male? Non portabile, sì, ma ha un effetto che non puoi ottenere in nessun altro modo (vedi la mia risposta). – zwol

+0

No, non è male! È abbastanza utile. – sidyll

+8

@Zack: è malvagio perché confonde le persone che non conoscono la sintassi non portatile e non necessaria. – akappa