2009-11-03 10 views
6

I creado un nuevo proyecto con el segmento de código siguiente:¿Metacaracidad desconocida en C/C++ cadena literal?

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

resultante en la salida siguiente:

(Strange]

Así traducir '??)' -> ']'

Depuración muestra que mi cadena de caracteres * literal es en realidad ese valor y no es una traducción de secuencia. Obviamente, esta no es una secuencia de metacaracteres que haya visto alguna vez. ¿Algún tipo de secuencia de caracteres Unicode o amplia quizás? No obstante, no lo creo ... Intenté deshabilitar todas las configuraciones de proyectos relacionadas en vano.

¿Alguien tiene una explicación?

  • de búsqueda: 'signo de interrogación, signo de interrogación, llave de cierre' c C++ cadena literal
+0

Esta pregunta podría ayudarlo: http://stackoverflow.com/questions/1234582/purpose-of-trigraph-sequences-in-c –

+0

gracias ... Agregué la búsqueda en la parte inferior de mi publicación con la esperanza que las búsquedas futuras coincidirían con la construcción del doble signo de interrogación. Esta decisión de diseño (habilitándola por defecto) está en una palabra: 'insano'. Deje los trigraphs en el OS/UI que digo. – Marius

+1

Trigraphs se agregaron específicamente para los casos donde el OS/UI era insuficiente. Recuerde que C data de una época en que la UI era una conexión de 9600 baudios y ASCII estaba lejos de ser universal. – caf

Respuesta

18

Lo que están viendo que se llama un trigraph.

En lenguaje escrito por adultos, un signo de interrogación es suficiente para cualquier situación. No use más de uno a la vez y nunca volverá a ver esto.

GCC ignora los trigrafos por defecto porque casi nadie los usa de forma intencional. Habilítelos con la opción -trigraph o indique al compilador que le advierta sobre ellos con la opción -Wtrigraphs.

Visual C++ 2010 también los deshabilita de manera predeterminada y ofrece /Zc:trigraphs para habilitarlos. No puedo encontrar nada sobre las formas de habilitarlos o deshabilitarlos en versiones anteriores.

+0

+1, pero en realidad es un trigraph http://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C. –

+0

Has comentado rápidamente. Lo arreglé una vez que noté que realmente había tres personajes allí. Gracias. –

+8

¿Es realmente insistente la insinuación insultante de que Marius no es un adulto? Estoy a favor de mantener el voto bajo la suposición de que fue de buen humor, pero en realidad es bastante despreciativo y completamente innecesario. –

4

Eso es trigraph soporte. Puede evitar la interpretación trigraph al escapar ninguno de los personajes:

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

manera fácil de evitar la trigraph sorpresa: dividir un "??"Cadena literal en dos:

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

Edición
gcc tiene una opción para advertir sobre trigrafos: -Wtrigraphs (activado con -Wall también)
final de edición

Cotizaciones de las

estándar
 
    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

Como he mencionado varias veces, te está picando un trigraph. Ver esta pregunta anterior SO para obtener más información:

puede solucionar el problema utilizando el '\?' secuencia de escape para el '?' Carácter:

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

De hecho, esta es la razón por la que la secuencia de escape, que es algo misterioso si está al tanto de esos malditos trigrafos.

+0

Gracias por la respuesta ... debido a la naturaleza de este error, es imposible buscar una respuesta a menos que uno sepa que se trata de un trigraph. El problema con arreglarlo de esa manera es que estoy usando C generado a partir de un generador de analizador lex/yacc. He usado y creado mis propios trigraphs en mi Mac y creo que es el lugar del sistema operativo para manejar las secuencias de trigraph y no el compilador. De hecho, solo en VS 2010 cambiarán este comportamiento predeterminado. – Marius

+0

Sí, me imagino que buscar ayuda en esto sin saber qué es un trigraph presenta un grave problema de huevo y pollo. Si no puede cambiar la salida lex/yacc y tiene que usar un compilador que no ignore los trigrafos (VS2010 o GCC), entonces creo que tiene que ejecutar la salida lex/tacc a través de un filtro que lo hará cambia los trigraphs a inofensivos no trigráficos. –

+0

Si yacc está produciendo C incorrecta ("incorrecta" porque no puede analizar la gramática especificada si esa gramática contiene caracteres de interrogación consecutivos), eso es bastante pobre. De acuerdo, entonces solo es incorrecto debido a un error de C, pero si va a escribir herramientas de generación de código, creo que se encarga de manejar ambas características y las fallas de su idioma de destino. Pero si solo ha salido mal porque aparece un trigraph en una acción yacc, ese es el error del usuario por ponerlo allí. –

1

al tratar de cruzar a compilar el CCG se recogió mi secuencia como un trigraph:

Así que todo lo que hay que hacer ahora es averiguar cómo desactivar esto en proyectos por defecto, ya que sólo se puede ver la creación problemas para mi (Estoy usando un diseño de teclado de Estados Unidos de todos modos)

El comportamiento predeterminado en GCC es ignorar, pero dar una advertencia, que es mucho más sensata y es de hecho lo que Visual Studio 2010 adoptará como el estándar que yo sepa .

Cuestiones relacionadas