Propósito de las secuencias Trigraph en C ++?

128

De acuerdo con C ++ '03 Standard 2.3 / 1:

Antes de que tenga lugar cualquier otro procesamiento, cada aparición de una de las siguientes secuencias de tres caracteres ("secuencias trigráficas") se reemplaza por el carácter único indicado en la Tabla 1.

----------------------------------------------------------------------------
| trigraph | replacement | trigraph | replacement | trigraph | replacement |
----------------------------------------------------------------------------
| ??=      | #           | ??(      | [           | ??<      | {           |
| ??/      | \           | ??)      | ]           | ??>      | }           |
| ??’      | ˆ           | ??!      | |           | ??-      | ˜           |
----------------------------------------------------------------------------

En la vida real, eso significa que el código printf( "What??!\n" );dará como resultado la impresión What|porque ??!es una secuencia trigráfica que se reemplaza con el |carácter.

Mi pregunta es ¿con qué propósito de usar trigrafos? ¿Hay alguna ventaja práctica de usar trigrafos?

UPD : ¿En las respuestas se mencionó que algunos teclados europeos no tienen todos los caracteres de puntuación, por lo que los programadores no estadounidenses tienen que usar trigráficos en la vida cotidiana?

UPD2 : Visual Studio 2010 tiene el soporte de trigraph desactivado de manera predeterminada.

Kirill V. Lyadvinsky
fuente
Algunos de los signos de puntuación son más difíciles de alcanzar en los teclados europeos (hasta el punto de que algunos programadores usan el diseño de EE. UU. Para escribir más rápido) ¿No he visto uno en el que falten los signos de puntuación por completo?
peterchen 03 de
2
Puede suceder que algunas terminales y / o virtualizaciones no le permitan acceder fácilmente a algunos caracteres. En mi experiencia, el delincuente principal es la tilde.
Francesco el
1
escribiendo esto en mi teclado DE-deadkeys, # es una tecla al lado de regresar, \ es "AltGr" + "ß" (al lado de 0), ^ es "^" + "^" (debido a las teclas muertas; al lado de 1) , [es "AltGr" + "8",] es "AltGr" + "9", | es "AltGr" + "<", {es "AltGr" + "7",} es "AltGr" + "0", y ~ es "~" + "~" (debido a las teclas muertas, justo encima de #). así que no es gran cosa. mis dedos son como escribir estas combinaciones por su cuenta :-D
nonchip
1
Pensé que es normal tener dos diseños de teclado y cambiarlos de acuerdo con el trabajo que estoy haciendo en la computadora. Es la forma común en la región de Europa central. Es bastante espeluznante usar estos trigrafos. Yo votaría por eliminar esto del estándar.
VX
1
@VX ¡Tienes tu deseo!
graham.reeds

Respuestas:

98

Esta pregunta (sobre los dígrafos estrechamente relacionados) tiene la respuesta.

Se reduce al hecho de que el conjunto de caracteres ISO 646 no tiene todos los caracteres de la sintaxis C, por lo que hay algunos sistemas con teclados y pantallas que no pueden manejar los caracteres (aunque imagino que estos son bastante raros hoy en día).

En general, no necesita usarlos, pero necesita saber acerca de ellos para saber exactamente el problema que encontró. Los trígrafos son la razón por la cual el ?personaje ' ' tiene una secuencia de escape:

'\?'

Entonces, un par de formas en que puede evitar su problema de ejemplo son:

 printf( "What?\?!\n" ); 

 printf( "What?" "?!\n" ); 

Pero tienes que recordar cuando estás escribiendo los dos '?' personajes en los que podrías comenzar un trigraph (y ciertamente nunca es algo en lo que esté pensando).

En la práctica, los trigrafos y los digráficos son algo de lo que no me preocupo en absoluto en el día a día. Pero debes estar al tanto de ellos porque una vez cada dos años te encontrarás con un error relacionado con ellos (y pasarás el resto del día maldiciendo su existencia). Sería bueno si los compiladores pudieran configurarse para advertir (o error) cuando se trata de un trígrafo o un dígrafo, por lo que podría saber que tengo algo con lo que debo tratar a sabiendas.

Y solo para completar, los dígrafos son mucho menos peligrosos ya que se procesan como tokens, por lo que un dígrafo dentro de un literal de cadena no se interpretará como un dígrafo.

Para una buena educación sobre diversas diversiones con puntuación en programas C / C ++ (incluido un error de trigraph que definitivamente me haría arrancarme el pelo), eche un vistazo al artículo GOTW # 86 de Herb Sutter .


Apéndice:

Parece que GCC no procesará (y advertirá sobre) los trigrafos de forma predeterminada. Algunos otros compiladores tienen opciones para desactivar el soporte de trigraph (por ejemplo, de IBM). Microsoft comenzó a admitir una advertencia (C4837) en VS2008 que debe habilitarse explícitamente (usando -Wall o algo así).

Michael Burr
fuente
La compatibilidad con C es la única razón? ¿Es posible cumplirlos en los programas modernos de C ++?
Kirill V. Lyadvinsky
Sí, C ++ también admite trigrafos y digráficos.
Michael Burr
44
Como recuerdo, al menos un compilador que he usado (g ++?) Requiere una opción de línea de comando explícita antes de traducir el trigraph y / o digraph, de lo contrario se da una advertencia pero no hay sustitución.
KTC
1
@ Jla3ep - Personalmente, nunca he tenido necesidad de trigrafos, pero desafortunadamente los compiladores procesarán el código con ellos, por lo que debe conocerlos (para evitar el uso accidental). Además, si obtiene código de otro lugar, puede encontrarse con su uso intencional, pero eso sería extremadamente inusual. Creo que me he encontrado con trigrafos usados ​​intencionalmente una vez en más de 20 años (era un código para un mainframe de IBM).
Michael Burr
1
Realmente solo me pone nervioso cuando los trigrafos se expanden en los comentarios para hacer cosas sorprendentes.
Joshua
23

¡Niños hoy! :-)

Sí, equipos extranjeros, como un terminal IBM 3270. El 3270 no tiene, si mal no recuerdo, llaves. Si deseaba escribir C en un mini / mainframe de IBM, tenía que usar los trígrafos miserables para cada límite de bloque. Afortunadamente, solo tuve que escribir software en C para emular algunas instalaciones de minicomputadora de IBM, en realidad no escribir software C en el Sistema / 36.

Mira al lado de la tecla "P":

teclado

Hmmm Difícil de decir. Hay un botón adicional al lado de "retorno de carro", y podría tenerlo al revés: tal vez era el par "[" / "]" que faltaba. En cualquier caso, este teclado le causaría dolor si tuviera que escribir C.

Además, estos terminales muestran EBCDIC, el juego de caracteres de mainframe "nativo" de IBM, no ASCII (gracias, Pavel Minaev, por el recordatorio).

Por otro lado, como dice la guía GNU C: "No necesitas este daño cerebral". El compilador gcc deja esta "característica" deshabilitada por defecto.

Roboprog
fuente
1
Hay un botón de reinicio en el teclado. ¡Eso es genial! Extraño que llamó mi atención primero sin embargo.
l46kok
11
Quien quiera usar C ++ 17 en una máquina EBCDIC, debería ser encarcelado por necrofilia.
SF.
A menos que una plataforma no tiene ningún carácter en absoluto distintas de aquellas en iso646, podría no todo lo que se puede hacer con trigrafos, puede hacer requiriendo que cada aplicación o bien definir una barra invertida o de lo contrario cualquier carácter que no está en el juego de caracteres C como una "meta", reemplace todas las referencias a la barra diagonal inversa en el Estándar con "meta" y agregue la barra diagonal inversa / meta escape para cualquier miembro del conjunto de caracteres C que no esté en ISO-646?
supercat
22

De The C++ Programming LanguageEdición especial, página 829

Los caracteres especiales ASCII [, ], {, }, |, y \ocupan posiciones de juego de caracteres alfabéticos designados como por la ISO. En la mayoría de los conjuntos de caracteres ISO-646 nacionales europeos, estas posiciones están ocupadas por letras que no se encuentran en el alfabeto inglés.

Se proporciona un conjunto de trigrafos para permitir que los caracteres nacionales se expresen de forma portátil utilizando un conjunto de caracteres mínimos verdaderamente estándar. Esto puede ser útil para el intercambio de programas, pero no facilita que las personas lean programas. Naturalmente, la solución a largo plazo para este problema es que los programadores de C ++ obtengan equipos que admitan tanto su idioma nativo como C ++. Desafortunadamente, esto parece inviable para algunos, y la introducción de nuevos equipos puede ser un proceso frustrantemente lento.

Robar
fuente
8
"La introducción de nuevos equipos puede ser un proceso frustrantemente lento". Especialmente comparado con el proceso rápido e indoloro de estandarizar las características del lenguaje de programación.
jforberg
44
Si esto es un error para las distribuciones de teclado, entonces es curioso que no haya un trigrafo, por ejemplo, para escribir `, que falta en el italiano y en otras
distribuciones de
15

Se utilizan en sistemas que carecen de algunos de los caracteres en el conjunto de caracteres básicos de C ++. No hace falta decir que tales sistemas son extremadamente raros.

CB Bailey
fuente
2
¿Eso significa que nunca los usaré en la vida real?
Kirill V. Lyadvinsky
1
¿En qué país vive usted? No todos los teclados para todos los idiomas tienen las teclas necesarias.
David Thornley
2
Sí, pero es posible que tenga que estar al tanto de su existencia en caso de que uno cause un resultado inesperado cuando se le presenta, digamos, un literal de cadena.
CB Bailey
44
@David Thornley: la mayoría de los sistemas modernos admiten todos los caracteres básicos de C ++ incluso si no están en el lugar convencional o requieren una secuencia modificadora para escribir. Los trígrafos solo necesitaban mantenerse en el código fuente en los sistemas en los que el carácter no puede representarse realmente en el conjunto de caracteres del sistema. Todavía mantengo que tales sistemas son extremadamente raros.
CB Bailey
9

Se han propuesto trígrafos para su eliminación en C ++ 0x. Dicho esto, todavía parece haber un fuerte argumento en apoyo de ellos: vea el documento del comité C ++ N2910 que discute esto. Aparentemente, EBCDIC es una fortaleza importante donde se necesitan.

Pavel Minaev
fuente
Sí, ese "idioma extranjero"! :-)
Roboprog
Realmente no dicen mucho, excepto "resultados de una encuesta interna de comentarios de los clientes", pero bueno. Me sorprende que EBCDIC se encuentra todavía en uso generalizado, aunque (y que estos sistemas exige que el uso de C ++ 0x compiladores)
Peterchen
5

He visto trigrafos utilizados a principios de los 90 para ayudar a convertir programas PL / 1 de un mainframe para ejecutar / compilar / depurar en una PC.

Estaban incursionando en la edición de PL / I en la PC usando un compilador de PL / I a C y querían que el código funcionara cuando volvieran a la unidad central que no admitía llaves. Sugerí que podrían usar macros como

#def BEGIN {    
#def END }  

o como una alternativa PL / I más amigable

#def BEGIN ??<
#def END ??>

y si realmente quisieran ponerse elegantes podrían intentar

#ifdef MAINFRAME
    #def BEGIN ??<
    #def END ??>
#else
    #def BEGIN {    
    #def END }  
#endif

y luego el programa se vería como si estuviera escrito en Pascal. Simplemente me miraron divertido y no me hablaron por el resto del día. No creo que los culpe. :)

Lo que mató el esfuerzo, no los tres gráficos, fueron las diferencias del sistema IO entre las plataformas. Abrir archivos en la PC era tan diferente al mainframe que habría introducido demasiados errores para mantener el mismo código ejecutándose en ambos.

Kelly S. French
fuente
PL / 1 = versión de IBM de C (más o menos). Vea mi comentario: los terminales de IBM no tienen teclas '{' / '}' :-( Tipo de C [++] difícil de escribir en uno de estos, de lo contrario.
Roboprog
3

Principalmente porque el estándar C los introdujo en 1989, cuando había problemas con la presencia de los caracteres a los que se asignan los trigrafos en algunas máquinas. Cuando se publicó el estándar C ++ en 1998, la necesidad de trigrafos no era grande. Son una verruga en C; son tanto una verruga en C ++. Había una necesidad de ellos, especialmente fuera del mundo de habla inglesa, por lo que se agregaron a C.

Jonathan Leffler
fuente
1
Siempre sospeché que IBM no hablaba inglés :-)
Roboprog
3

Algunos teclados europeos no tienen (¿no?) Todos los caracteres de puntuación que tenían los teclados de EE. UU., Ya que necesitaban las teclas para sus caracteres alfabéticos inusuales. Entonces, por ejemplo (inventando esto), el teclado sueco tendría un anillo A donde estaba la llave.

Para acomodar a esos usuarios, los trigrafos son una forma de ingresar signos de puntuación usando solo los caracteres ASCII más comunes.

Ned Batchelder
fuente
44
Los trígrafos no son realmente sobre la entrada de datos (hacen que el código sea bastante ilegible), son más sobre sistemas que en realidad no tienen los caracteres requeridos. Si un sistema puede grabar y mostrar el carácter, incluso si se necesita escribir una secuencia de teclas similar a un trigrafo, sería mucho más fácil no retener la secuencia de trigraph en la fuente.
CB Bailey
2

Están allí principalmente por razones históricas. Hoy en día, la mayoría de los teclados modernos para la mayoría de los idiomas permiten el acceso a todos esos caracteres, pero esto solía ser un problema una vez con algunos teclados europeos. Por eso se inventaron los trigrafos.

Si no sabes para qué sirven, no deberías usarlos.

Sin embargo, todavía es bueno estar al tanto de ellos, ya que puede usar uno accidental y accidentalmente en su código.

sbi
fuente