2015-05-18 10 views
13

Una risposta alla domanda Disable check for override in gcc ha suggerito di utilizzare -Doverride= sulla riga di comando per disattivare gli errori per l'uso errato di override, che è effettivamente la stessa come l'aggiunta di:È un comportamento non definito per # define/# undef un identificatore con un significato speciale?

#define override 

al file di origine.

La mia reazione iniziale è stata che questo mi sembra un comportamento indefinito poiché stiamo ridefinendo una parola chiave, ma guardando la parte standard progetto C++ 11 2.12Parole [lex.key] mi ha sorpreso nessuno che esclusionefinale sono parole chiave. Sono coperti nella sezione precedente 2.11[lex.name] che dice che sono identificatori con significato speciale:

Gli identificatori nella tabella 3 hanno un significato speciale quando appare in un certo contesto [... ]

e Tabella 3 è etichettato identificatori con significato speciale e comprende sia sostituzione e finale.

La domanda è, è un comportamento indefinito di ridefinire (utilizzando # define) identificatori con significato speciale? Sono trattati in modo diverso rispetto alle parole chiave in questo senso?

+0

Che cosa è "ridefinire" una macro di pre-processore o una dichiarazione? –

+0

@ DieterLücking buona cattura, voglio dire con '# define', modificato per chiarire. –

+0

@benvoigt questi sono completamente diversi domanda –

risposta

12

Se si utilizza la libreria standard C++ è un comportamento indefinito di ridefinire identificatori con significato speciale, questo vale anche per le parole chiave . Dalla bozza di standard C++ 11 ai sensi della sezione 17.6.4[vincoli] dobbiamo sezione 17.6.4.1[constraints.overview] che dice:

Questa sezione descrive restrizioni su C++ programmi che utilizzano le strutture del libreria standard C++ [...]

e sotto 17.6.4 abbiamo sezione 17.6.4.3.1[macro.names] che dice:

0.123.

Un'unità definizione non #define o nomi #undef lessicalmente identiche alle parole chiave, agli identificatori elencati nella tabella 3, o agli attributi -token descritti in 7.6.

Tabella 3 lista dei identificatori con significato speciale. Possiamo vedere che questo paragrafo copre anche le parole chiave e sono trattate allo stesso modo.

+0

Chiesto e ha risposto nello stesso minuto da la stessa persona - mmm. –

+2

@ DieterLücking per favore vedi [Posso rispondere alle mie stesse domande, anche se conoscessi la risposta prima di chiedere?] (Http://meta.stackexchange.com/q/17463/213111) –

+1

In questo modo, dovresti avere una definizione ben definita titolo e domanda. –

1

I file di intestazione standard delle implementazioni sono autorizzati a "implementare" le funzioni standard utilizzando le macro nei casi in cui una macro possa soddisfare i requisiti per la funzione (incluso assicurare che gli argomenti vengano valutati esattamente una volta). Inoltre, tali macro possono utilizzare parole chiave o identificatori il cui comportamento è specificato nello standard o "riservato all'implementazione"; l'uso di tali macro in contesti in cui le parole chiave o gli identificatori sono stati ridefiniti potrebbe avere effetti arbitrari.

Ciò detto, l'interpretazione storica di questa forma di UB sarebbe quello di dire che i compilatori non devono andare fuori del loro modo di causare un comportamento stravagante, e al di fuori dei "modi pedanti" dovrebbe consentire di codice all'utente di assegnare significati per gli identificatori riservati altrimenti non verrebbe utilizzato dal compilatore. Questo può essere utile nei casi in cui il codice dovrebbe essere utilizzabile sia su compilatori che richiederebbero una parola chiave come __packed, sia su compilatori che non riconoscono né richiedono tale parola chiave.). Ridefinire le parole chiave nella moda che stai facendo è un po 'più incerto; probabilmente funzionerà, ma c'è una significativa probabilità che interrompa il comportamento di una macro di libreria standard.

+0

'... permesso di" implementare "le funzioni standard usando le macro' - Davvero? Hanno bisogno di supportare l'assunzione di un indirizzo di una funzione così "implementata"? – Nemo

+0

Non definire una funzione come macro crea regole di scoping diverse? Es: se printf() era una macro, non potevo avere una variabile locale chiamata printf. –

+0

@MobyDisk: è legale avere una variabile locale denominata 'printf' all'interno di un'unità di conversione che include' '? Pensavo che fosse un comportamento indefinito (sebbene in pratica di solito ombreggia la funzione printf esterna come se il nome esterno non esistesse o producesse errori di compilazione, piuttosto che deformare il tessuto del tempo e della causalità). – supercat

Problemi correlati