2009-11-03 19 views
6

Ho creato un nuovo progetto con il seguente segmento di codice:Meta-carattere sconosciuto in stringa letterale C/C++?

char* strange = "(Strange??)"; 
cout << strange << endl; 

conseguente il seguente output:

(Strano]

Così tradurre '??)' -> ']'

Il debugging mostra che il mio char * string letteral è in realtà quel valore e non è una traduzione stream. Questa ovviamente non è una sequenza di meta-personaggi che abbia mai visto. Qualche tipo di sequenza Unicode o ampia char, forse? Tuttavia, io non la penso così ... Ho provato a disabilitare tutte le impostazioni relative al progetto inutilmente.

Chiunque ha una spiegazione?

  • ricerca: 'punto interrogativo, punto interrogativo, vicino brace' c C++ stringa letterale
+0

Questa domanda può aiutarti: http://stackoverflow.com/questions/1234582/purpose-of-trigraph-sequences-in-c –

+0

grazie ... Ho aggiunto la ricerca in fondo al mio post nella speranza che le ricerche future corrispondessero al doppio controlo del punto interrogativo. Questa decisione di progettazione (abilitandola come predefinita) è in una parola: "insano". Lasciare i trigrafi al sistema operativo/interfaccia utente che dico. – Marius

+1

I trigrammi sono stati specificatamente aggiunti per i casi in cui il sistema operativo/interfaccia utente era insufficiente. Ricorda che C risale a un tempo in cui l'interfaccia utente era una connessione terminale a 9600 baud e ASCII era tutt'altro che universale. – caf

risposta

18

Quello che stai vedendo è chiamato un trigraph.

In linguaggio scritto da adulti, un punto interrogativo è sufficiente per qualsiasi situazione. Non usare più di uno alla volta e non lo vedrai mai più.

GCC ignora i trigraph di default perché quasi nessuno li usa intenzionalmente. Abilitali con l'opzione -trigraph, o dì al compilatore di avvertirti su di loro con l'opzione -Wtrigraphs.

Visual C++ 2010 li disabilita anche per impostazione predefinita e offre /Zc:trigraphs per attivarli. Non riesco a trovare nulla sui modi per abilitarli o disabilitarli nelle versioni precedenti.

+0

+1, ma in realtà è un trigramma http://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C. –

+0

Hai commentato rapidamente. L'ho risolto quando ho notato che c'erano davvero tre personaggi lì. Grazie. –

+8

È insinuante l'insinuazione che Marius non sia un adulto davvero necessario? Sto tenendo premuto il voto sull'ipotesi che fosse inteso con buon umore, ma è davvero piuttosto riduttivo e del tutto superfluo. –

4

Questo è il supporto trigraph. È possibile impedire l'interpretazione trigraph fuggendo qualsiasi dei caratteri:

char* strange = "(Strange?\?)"; 
6

modo semplice per evitare la sorpresa trigraph: dividere un "??"Stringa letterale in due:

char* strange = "(Strange??)"; 
char* strange2 = "(Strange?" "?)"; 
/*       ^^^ no punctuation */ 

Modifica
gcc ha un'opzione per mettere in guardia su trigrammi: -Wtrigraphs (abilitata con -Wall anche)
fine modificare

Citazioni dal standard

 
    5.2.1.1 Trigraph sequences 
1 Before any other processing takes place, each occurrence of one of the 
    following sequences of three characters (called trigraph sequences13)) 
    is replaced with the corresponding single character. 
      ??=  #    ??)  ]    ??!  | 
      ??(  [    ??' ^    ??>  } 
      ??/  \    ??<  {    ??-  ~ 
    No other trigraph sequences exist. Each ? that does not begin one of 
    the trigraphs listed above is not changed. 
 
    5.1.1.2 Translation phases 
1 The precedence among the syntax rules of translation is specified by 
    the following phases. 
     1. Physical source file multibyte characters are mapped, in an 
       implementation-defined manner, to the source character set 
       (introducing new-line characters for end-of-line indicators) 
       if necessary. Trigraph sequences are replaced by corresponding 
       single-character internal representations. 
2

Come accennato più volte, sei stato morso da un trigramma. Vedere questo precedente domanda Così, per ulteriori informazioni:

è possibile risolvere il problema utilizzando il '\?' sequenza di escape per il '?' carattere:

char* strange = "(Strange\?\?)"; 

In realtà, questo è il motivo di tale sequenza di escape, che è un po 'misterioso, se siete a conoscenza di quei maledetti trigraph.

+0

Grazie per la risposta ... a causa della natura di questo bug è impossibile cercare una risposta a meno che non si sappia che è un trigramma. Il problema con il fissaggio in questo modo è che sto usando generato C da un generatore di parser lex/yacc. Ho usato e creato i miei trigraph sul mio Mac e penso che sia il posto del sistema operativo per gestire le sequenze di tastiera del trigramma e non il compilatore. Infatti solo in VS 2010 cambieranno questo comportamento predefinito. – Marius

+0

Sì, posso immaginare che cercare aiuto su questo senza sapere già che cosa è un trigramma è un serio problema di pollo e uova. Se non riesci a cambiare l'output di lex/yacc e devi usare un compilatore che non ignori i trigraph (VS2010 o GCC), allora penso che sei bloccato a dover eseguire l'output lex/tacc attraverso un filtro che cambiare i trigrafi in non-trigrafi innocui. –

+0

Se yacc sta emettendo in modo errato C ("errato" perché non riesce ad analizzare la grammatica specificata se la grammatica contiene caratteri di punti interrogativi consecutivi), questo è piuttosto scarso. OK, quindi è solo errato a causa di una disfunzione di C, ma se hai intenzione di scrivere strumenti di generazione del codice, penso che tu prenda te stesso per occuparti di entrambe le caratteristiche e le disfunzioni della tua lingua di destinazione. Ma se è andato male solo perché un trigraph appare in un'azione yacc, questo è l'errore dell'utente nel metterlo lì. –

1

Durante il tentativo di cross-compilare su GCC raccolse la mia sequenza come un trigraph:

Quindi tutto quello che dovete fare ora è capire come disattivare questo in progetti di default dal momento che posso vedere solo la creazione di problemi per me. (Sto usando comunque un layout di tastiera statunitense)

Il comportamento predefinito su GCC è ignorare ma fornire un avviso, che è molto più sano di mente ed è effettivamente ciò che Visual Studio 2010 adotterà come standard per quanto ne so .

Problemi correlati