5

In base allo standard C11, un argomento di una macro simile a una funzione può contenere spazi bianchi all'inizio o alla fine della sequenza di token di pre-elaborazione. Per la sostituzione normale, questo tipo di spazi non ha effetti. Per la stringificazione, gli spazi devono essere ignorati come indicato in 6.10.3.2.2Argomenti macro del preprocessore C con spazio alla fine per concatenare?

Lo spazio bianco prima del primo token di preelaborazione e dopo l'ultimo token di preprocessing che compone l'argomento viene eliminato.

(che a mio avviso è anche una prova dimostrando che gli argomenti possono contenere spazi intorno ad esso.) E la questione è, per gli argomenti che sarebbero concatenati da ## operatori, che cosa dovrebbe fare il compilatore sui suoi spazi?

Ho provato con VC++, che sembra ignorare gli spazi.

Penso che il compilatore debba eseguire la concatenazione con spazi bianchi. Ciò può comportare un token non valido, ad esempio "ABC" formato dall'identificatore ABC e un argomento con uno spazio bianco come primo token. Secondo lo standard, se un token non valido viene formato in questo modo, il comportamento non è definito.

Quindi, per ciò che VC++ ha fatto come accennato in precedenza, è il risultato del semplice ignorare lo spazio o il risultato del comportamento non definito?

risposta

4

che a mio avviso è anche una prova dimostrando che gli argomenti possono contenere spazi intorno ad esso

No, in realtà non fa che rafforzare disposizione del standard che ogni argomento macro è una sequenza di token pre-elaborazione(C2011, 6.10.3/11). Gli spazi bianchi nel file sorgente separano i token di preelaborazione; le corse di spazi bianchi non sono pre-processare i token stessi.

La sezione dello standard citato è potenzialmente confusa perché mischia i livelli: la sequenza di caratteri del file di origine, a cui appartiene lo spazio bianco e la sequenza di token di preelaborazione derivante dalla tokenizzazione iniziale della sequenza sorgente. In effetti, la stringificazione è sensibile al fatto che i token adiacenti siano separati da spazi bianchi nella sequenza dei caratteri di origine, ma i dettagli di tali spazi non hanno alcuna importanza - dopo la stringificazione, i token adiacenti che erano separati da spazio bianco sono separati da un singolo spazio carattere nella stringa risultante.

Ciò non significa che un token di preelaborazione può iniziare o terminare con spazi vuoti. Non può; vedere la sezione 6.4 dello standard per i dettagli completi.Il modo in cui una determinata implementazione soddisfa le specifiche per la stringificazione è necessariamente specifica dell'implementazione, ma un modo in cui un'implementazione potrebbe farlo implicherebbe il mantenimento di flag booleani per ogni token di preelaborazione che descrive se tale token è preceduto e/o seguito nella sequenza sorgente da spazi bianchi. Tali dettagli non hanno nulla a che fare con l'interpretazione di ciò che lo standard specifica per il risultato, tuttavia, né per l'operatore di stringa né per l'operatore di token che incolla.

per argomenti che sarebbero concatenati dall'operatore ##, cosa dovrebbe fare il compilatore in merito ai suoi spazi?

Con il tempo il ## dell'operatore (o l'operatore #) entra in gioco, il compilatore ha già fatto tutto lo sarà mai (direttamente) che fare con caratteri di spazio che appaiono nel file di origine, considerandoli durante la tokenizzazione di la fonte nei token di preelaborazione. Gli argomenti macro sono sequenze di token di preelaborazione e solo nella misura in cui tali token possono essere stringhe o caratteri letterali o nomi di intestazione potrebbero contenere spazi bianchi. Inoltre, lo standard specifica:

Se, nell'elenco sostituzione di una macro funzione simile, un parametro è immediatamente preceduta o seguita da una ## preelaborazione gettone, il parametro è sostituito dal dell'argomento corrispondente preelaborazione gettone sequenza [...]

(C2011, 6.10.3.3/2; enfasi aggiunta)

gettoni ancora una volta, corre spazi bianchi non sono pre-elaborazione. L'espansione macro e gli operatori # e ## si occupano e operano a livello di sequenze di token di preelaborazione. Gli spazi bianchi sono rappresentati a questo livello solo internamente all'interno di token. Gli spazi bianchi dal file sorgente che non sono interni a un token di preelaborazione sono rappresentati solo indirettamente e in modo incerto nella sequenza di token di preelaborazione.

+0

Vedo. Grazie mille per la tua risposta. Ma mi chiedo, se il compilatore non include lo spazio bianco nella sequenza di token di pre-elaborazione dell'argomento, come farà la stringa? Voglio dire, come dovrebbe sapere dove mettere lo spazio bianco tra i token di pre-elaborazione adiacenti e dove no. Immagino che non solo registri la sequenza di token ma anche informazioni sugli spazi bianchi? Cosa dice lo standard su questo? –

+0

@WuZhenwei, hai ragione che la stringa non inserisce spazi bianchi tra i token di pre-elaborazione dove non ce n'è alcuno nella sequenza dei caratteri sorgente. Poiché al preprocessore non interessa * quanto * spazio ci sia o quali siano i caratteri dello spazio bianco specifici in tali luoghi, esso può tracciare token token se i token sono preceduti e/o seguiti da spazi bianchi. Questo è un dettaglio di implementazione. Aggiornerò la mia risposta per chiarire. –

3

6.10.3.3/3

prima che la lista di sostituzione è riesaminati per maggiori nomi delle macro per sostituire, ogni istanza di un ## pre-elaborazione di token nella lista di sostituzione (non da un argomento) viene eliminato e il precedente token di pre-elaborazione è concatenato con il seguente token di pre-elaborazione.

Quindi ## concatena due token di preelaborazione. È irrilevante se gli argomenti da cui sono tratti contengono spazi bianchi.

+0

Vuoi dire che è una specie di comportamento indefinito che VC++ sta ignorando lo spazio? (Vedi l'ultima frase della mia domanda.) –

+1

@WuZhenwei no Non intendo niente del genere. La tua ultima frase si basa su una premessa non valida, vale a dire che il preprocessore dovrebbe concatenare gli spazi bianchi. Non c'è nulla nello standard che lo dice. –

+0

Grazie. Pensavo che lo spazio bianco potesse anche essere un token di preelaborazione. –

Problemi correlati