Domanda

per quanto ne so, questa domanda vale anche per C e C ++

Passo 6 delle "fasi" traduzione specificati nel C standard (5.1.1.2 nel progetto di norma C99) indica che adiacenti stringhe letterali devono essere concatenati in un singolo letterale. Vale a dire

printf("helloworld.c" ": %d: Hello "
       "world\n", 10);

è equivalente (sintatticamente) a:

printf("helloworld.c: %d: Hello world\n", 10);

Tuttavia, lo standard non sembra indicare quale parte del compilatore deve gestire questo - dovrebbe essere il preprocessore (cpp) o il compilatore stesso. Alcune ricerche on-line mi dice che questa funzione è in genere dovrebbe essere eseguita dal preprocessore ( fonte # 1 , fonte # 2 , e ci sono più), che ha un senso.

Tuttavia, l'esecuzione cpp in spettacoli Linux che cpp non lo fa:

eliben@eliben-desktop:~/test$ cat cpptest.c 
int a = 5;

"string 1" "string 2"
"string 3"

eliben@eliben-desktop:~/test$ cpp cpptest.c 
# 1 "cpptest.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpptest.c"
int a = 5;

"string 1" "string 2"
"string 3"

Quindi, la mia domanda è: dove dovrebbe questa caratteristica del linguaggio essere gestita, nel preprocessore o compilatore stesso

Forse non c'è una risposta unica buona. saranno apprezzati risposte euristiche basate sull'esperienza, compilatori noti, e in generale la pratica di ingegneria buona.


P.S. Se vi state chiedendo il motivo per cui mi interessa questo ... sto cercando di capire se il mio Python basato C parser dovrebbe gestire concatenazione di stringhe letterali (che non fa, al momento), o lasciare che sia cpp che assume viene eseguito prima di esso.

È stato utile?

Soluzione

La norma non specifica un preprocessore contro un compilatore, solo specifica le fasi di traduzione che già notato. Tradizionalmente, le fasi da 1 a 4 erano nel preprocessore, Fasi 5 sebbene 7 nel compilatore, e la fase 8 il linker -. Ma nessuno di che è richiesto dalla norma

Altri suggerimenti

A meno che il preprocessore è specificato per gestire questa situazione, è lecito ritenere che il lavoro del compilatore.

Modifica:

Il link " Ie " all'inizio del post risponde alla domanda:

  

stringhe letterali adiacenti sono concatenati al momento della compilazione; questo permette lunghe stringhe di essere suddiviso su più righe, e permette anche letterali stringa risultanti da C preprocessore definisce e macro che viene acclusa in stringhe in fase di compilazione ...

Nello standard ANSI C, questo dettaglio è illustrato nella sezione 5.1.1.2, punto (6):

  

5.1.1.2 fasi di traduzione
  ...
  
  4. direttive al preprocessore vengono eseguiti e invocazioni macro sono espansi. ...
  
  5. Ciascuna sorgente membro set di caratteri e la sequenza di fuga in costanti carattere e stringhe viene convertito in un membro del set di caratteri esecuzione.
  
  6. gettoni letterali stringa di caratteri adiacenti sono concatenati e gettoni letterali stringa ampia adiacenti sono concatenati.

Lo standard non definisce che l'applicazione deve utilizzare un pre-processore e compilatore, di per sé.

Passo 4 è chiaramente una responsabilità preprocessore.

Passo 5 richiede che il "set di caratteri di esecuzione" essere conosciuto. Questa informazione è richiesto anche dal compilatore. È facile porta al compilatore di una nuova piattaforma se il preprocessore non contiene dependendencies piattaforma, per cui la tendenza è quella di attuare passaggio 5 e quindi passaggio 6, nel compilatore.

Ci sono regole difficili per quanti stringa interagisce concatenazione letterale con sequenze di escape. Si supponga di avere

const char x1[] = "a\15" "4";
const char y1[] = "a\154";
const char x2[] = "a\r4";
const char y2[] = "al";

quindi x1 e x2 devono finire pari secondo la strcmp, e lo stesso per y1 e y2. (Questo è ciò che Heath è sempre a nel citare le fasi di traduzione - la conversione di fuga accade prima stringa costante concatenazione.) C'è anche un requisito che, se qualsiasi delle costanti stringa in un gruppo concatenazione ha un prefisso L o U, si ottiene una stringa di larghezza o Unicode. Mettere tutto insieme e si finisce per essere molto più conveniente per fare questo lavoro come parte del "compilatore" piuttosto che il "preprocessore".

vorrei gestirlo nella parte pegno la scansione del parser, quindi nel compilatore. Sembra più logico. Il preprocessore non ha di conoscere la "struttura" della lingua, e in effetti lo ignora di solito in modo che le macro possono generare il codice uncompilable. Gestisce niente di più di quello che ha il diritto di manico dalle direttive che sono indirizzati specificamente ad esso (# ...), e le "conseguenze" di essi (come quelle di un #define x h, che renderebbe il cambiamento preprocessore un sacco di x in h)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top