2015-06-24 2 views
8

Ho un piccolo problema con un preprocessore che mi imbarazza e non riesco a trovare alcuna spiegazione nella documentazione/preprocessore/lingua specifica.Perché il preprocessore C/C++ aggiunge uno spazio qui?

#define booboo() aaa 
booboo()bbb 
booboo().bbb 

viene pre-elaborato in:

aaa bbb <--- why is space added here 
aaa.bbb 

Dopo la manipolazione trigrammi, linee e commenti continuato, preprocessore funziona su direttive del preprocessore e si divide in ingresso in token pre-elaborazione e spazi bianchi. L'elenco di sostituzione di booboo comprende un token-token che è identificativo 'aaa'. booboo() bbb è diviso in token-to-pe: 'booboo', '(', ')', 'bbb'. La sequenza di 'booboo', '(', ')' è riconosciuta come invocazione macro funzionale e dovrebbe essere estesa a 'aaa' e imho in output dovrebbe apparire come 'aaabbb'. Ho detto che sembra che - per l'umano - assomiglierebbe a un token mentre il compilatore otterrebbe 2 token 'aaa' e 'bbb' poiché non è stato utilizzato alcun operatore '##' che consente la concatenazione di token in token. Perché/quale regola rende il preprocessore cpp (c) spazio aggiuntivo tra 'aaa' e 'bbb' quando 'booboo(). Bbb' risulta in 'aaa.bbb' senza spazio?

Ciò è dovuto al fatto che cpp tenta di rendere l'output (che è per lo più umano) non ambiguo? Umano non è in grado di dire che 'aaabbb' è composto da 2 token poiché vede solo l'ortografia dei token. Ho ragione? Ho letto la documentazione C99 sul preprocessore e la documentazione di gcc per cpp. Non vedo nulla al riguardo.

Se ho ragione abbiamo situazione simile qui:

#define baba() + 
baba()+ 
baba()- 

risultati in:

+ + 
+- 

In caso contrario (se '++' è l'uscita) sarebbe risultato a un essere umano come ' ++ 'token ma ci sarebbero 2 token' + 'e' + '. È come con l'operatore '##' che cpp controlla se la concatenazione produce un token valido, ma nei casi mostrati vuole impedire all'uomo che tale concatenazione sia stata eseguita? '+ -' non è ambiguo quindi non viene aggiunto spazio

+1

Vale la pena notare: lo standard C non dice nulla sugli strumenti che si fermano a metà del processo di compilazione. – o11c

+2

Correlati (possibile dup): [espansione cpp della macro senza token-string] (http://stackoverflow.com/questions/30813619/cpp-expansion-of-macro-with-no-token-string/30813841#30813841) –

+0

Si noti che molto spesso la spaziatura non ha importanza in C o C++. – MicroVirus

risposta

6

Il risultato della preelaborazione è trasformare il file sorgente in un elenco di token. Nel tuo caso l'elenco di token sarà simile, dopo tokenizzazione:

.... 
booboo() 
bbb 
.... 

e poi, dopo la sostituzione macro:

.... 
aaa 
bbb 
.... 

Poi il compilatore traduce l'elenco di token in un file eseguibile.

Lo spazio vuoto che si sta visualizzando è solo un dettaglio di implementazione che il compilatore, ecc., Ha scelto di disporre i token di preelaborazione quando si visualizza un risultato intermedio. Gli standard non dicono nulla sui file di elaborazione intermedi. Non è richiesto che ci sia un programma separato per eseguire la pre-elaborazione.

+4

@BlueMoon non ha bisogno di essere un preprocessore separato, quindi non deve fare nulla. Le fasi di pre-elaborazione della traduzione sono solo specificate come produrre una lista di token, non produrre un file. "L'output del preprocessore" è uno stadio intermedio tra il file sorgente e l'eseguibile. –

+0

@Matt: vorrei riformulare la risposta a sth come (imho meglio): "L'obiettivo della pre-elaborazione è trasformare il file sorgente in una lista di token che poi diventano input del compilatore Nel tuo caso (dopo la tokenizzazione) l'elenco di token assomiglierebbe a questo "e non direi che" booboo() "è un token ma 3 token. Il resto è chiaro e carino. – Artur

+1

@Blue Moon: "non c'è bisogno di essere un preprocessore separato" è diverso da "È vero che non c'è bisogno di essere un processore". Quello che Matt dice è che il compilatore non ha bisogno di vedere l'output del preprocessore nel modo in cui dovrebbe essere presentato a noi (umani). Il compilatore richiede solo token, niente spazi. La funzione del preprocessore che consente di produrre risultati del suo lavoro è solo per gli esseri umani in modo che possiamo eseguire il debug ... e avere meno grattacapo ;-) – Artur

-1

Ho scritto un compilatore ANSI C all'inizio degli anni '90. Per quanto mi ricordo, un token commento/....../dovrebbe essere sostituito da un singolo spazio bianco. Le macro sostituiscono il testo, sul posto. Non è necessario che i token risultanti dalla sostituzione del testo di tali macro espansioni siano token di linguaggio C legali. Quando una macro è definita come testo 'aaa', è solo quel testo 'aaa' che si fa strada nel flusso di input. Il parser di C può o non può visualizzare token validi come risultato di ciò!

Quindi, dato:

definire booboo() aaa

espandibile booboo() bbb dovrebbe comportare testo aaabbb

Cosa che aaabbb medio è lasciata all'utente. Ma quel aaabbb non sarà preelaborato anche se capita di essere il nome di una macro. Questo è sicuro. Ma aaabbb potrebbe essere un identificativo utente - nessun problema lì.

+2

Questo concatenerebbe diversi token, cosa che non accade. – Eiko

+1

C'è una direttiva separata '##' per concatenare i token. – MicroVirus