Objetivo das seqüências de Trigraph em C ++?

127

De acordo com o C ++ '03 Standard 2.3 / 1:

Antes de qualquer outro processamento, cada ocorrência de uma das seguintes seqüências de três caracteres ("sequências trigrafônicas") é substituída pelo caractere único indicado na Tabela 1.

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

Na vida real, isso significa que o código printf( "What??!\n" );resultará na impressão, What|pois ??!é uma sequência de trigramas que é substituída pelo |caractere.

Minha pergunta é qual o objetivo de usar trigramas? Existe alguma vantagem prática de usar trigramas?

UPD : Nas respostas foi mencionado que alguns teclados europeus não têm todos os caracteres de pontuação, então os programadores não americanos precisam usar trigramas no dia a dia?

UPD2 : O Visual Studio 2010 tem o suporte a trigrafs desativado por padrão.

Kirill V. Lyadvinsky
fonte
Parte da pontuação é mais difícil de ser alcançada em teclados europeus (a ponto de alguns programadores usarem o layout dos EUA para digitar mais rápido).
Peterchen
2
Pode acontecer que alguns terminais e / ou virtualização não permitam o acesso fácil a alguns caracteres. Na minha experiência, o principal ofensor é o til.
Francesco
1
digitando isso no meu teclado DE-deadkeys, # é a tecla ao lado de retorno, \ é "AltGr" + "ß" (próximo a 0), ^ é "^" + "^" (por causa de teclas inoperantes; próximo a 1) , [é "AltGr" + "8",] é "AltGr" + "9", | é "AltGr" + "<", {é "AltGr" + "7",} é "AltGr" + "0" e ~ é "~" + "~" (por causa de teclas mortas, logo acima de #). então não é realmente grande coisa. meus dedos são como digitando estas combinações em seu próprio :-D
nonchip
1
Eu pensei que é normal ter dois layouts de teclado e trocá-los de acordo com o trabalho que estou fazendo no computador. É o caminho comum na região da Europa Central. É muito assustador usar esses trigramas. Eu votaria para remover isso do padrão.
VX
1
@VX Você tem o seu desejo!
graham.reeds

Respostas:

97

Esta pergunta (sobre os dígrafos intimamente relacionados) tem a resposta.

Tudo se resume ao fato de que o conjunto de caracteres ISO 646 não possui todos os caracteres da sintaxe C, portanto, existem alguns sistemas com teclados e displays que não conseguem lidar com os caracteres (embora eu imagine que sejam muito raros). hoje em dia).

Em geral, você não precisa usá-los, mas precisa conhecê-los exatamente para o problema que encontrou. Trígrafos são o motivo pelo qual o ?caractere ' ' tem uma sequência de escape:

'\?'

Portanto, algumas maneiras de evitar seu problema de exemplo são:

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

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

Mas você precisa se lembrar de quando digitar os dois '?' caracteres nos quais você pode estar iniciando um trígrafo (e certamente nunca é algo em que estou pensando).

Na prática, trigramas e dígrafos são algo com o qual não me preocupo no dia a dia. Mas você deve estar ciente deles, pois a cada dois anos você encontra um bug relacionado a eles (e passa o resto do dia amaldiçoando sua existência). Seria bom se os compiladores pudessem ser configurados para avisar (ou erro) quando se deparar com um trigrafo ou dígrafo, para que eu pudesse saber que tenho algo com o qual devo lidar conscientemente.

E, para completar, os dígrafos são muito menos perigosos, pois são processados ​​como tokens; portanto, um dígrafo dentro de uma string literal não será interpretado como um dígrafo.

Para uma boa educação sobre diversão com pontuação em programas C / C ++ (incluindo um bug de trigrafo que definitivamente me faria arrancar o cabelo), dê uma olhada no artigo GOTW # 86 de Herb Sutter .


Termo aditivo:

Parece que o GCC não processará (e avisará sobre) trigrafs por padrão. Alguns outros compiladores têm opções para desativar o suporte a trigraph (da IBM, por exemplo). A Microsoft começou a oferecer suporte a um aviso (C4837) no VS2008 que deve ser ativado explicitamente (usando -Wall ou algo assim).

Michael Burr
fonte
Compatibilidade com C é a única razão? É possível encontrá-los em modernos programas C ++?
Kirill V. Lyadvinsky
Sim, o C ++ também suporta trigramas e dígitos.
Michael Burr
4
Pelo que me lembro, pelo menos um compilador que usei (g ++?) Requer uma opção de linha de comando explícita antes da tradução do trigraph e ou do digraph, caso contrário, um aviso é dado, mas nenhuma substituição.
KTC
1
@ Jla3ep - Eu pessoalmente nunca precisei de trigramas, mas infelizmente os compiladores processam código com eles, então você precisa estar ciente deles (para evitar o uso acidental). Além disso, se você obtiver código de outro lugar, poderá usar intencionalmente, mas isso seria extremamente incomum. Acho que encontrei trigrafs usados ​​intencionalmente uma vez em mais de 20 anos (era algum código para um mainframe da IBM).
Michael Burr
1
Realmente só me dá nos nervos quando os trigramas são expandidos nos comentários para fazer coisas surpreendentes.
217 Joshua Joshua
23

Crianças hoje! :-)

Sim, equipamento externo, como um terminal IBM 3270. O 3270, se bem me lembro, não tem aparelho! Se você quisesse escrever C em um mini / mainframe IBM, teria que usar os trigraphs miseráveis ​​para cada limite de bloco. Felizmente, só precisei escrever software em C para emular algumas instalações de minicomputadores da IBM, e não escrever software C no System / 36.

Olhe ao lado da tecla "P":

teclado

Hummm. Difícil de dizer. Há um botão extra ao lado de "retorno de carro" e eu posso usá-lo ao contrário: talvez fosse o par "[" / "]" que estava faltando. De qualquer forma, este teclado causaria pesar se você tivesse que escrever C.

Além disso, esses terminais exibem o EBCDIC, o conjunto de caracteres mainframe "nativo" da IBM, não o ASCII (obrigado, Pavel Minaev, pelo lembrete).

Por outro lado, como o guia GNU C diz: "Você não precisa desse dano cerebral". O compilador gcc deixa esse "recurso" desativado por padrão.

Roboprog
fonte
1
Há um botão de reset no teclado. Fantástico! Estranho que chamou minha atenção primeiro.
L46kok # 26/13
10
Quem quiser usar o C ++ 17 em uma máquina EBCDIC deve ser preso por necrofilia.
SF.
A menos que uma plataforma não tem caracteres em tudo com excepção daquelas em ISO646, poderia nem tudo o que pode ser feito com trigraphs, ser feito através da exigência de que cada implementação definir uma barra invertida, ou então qualquer caractere que não está no conjunto de caracteres C como um caractere "meta", substitua todas as referências à barra invertida no padrão por "meta" e adicione barras invertidas / meta escapes para quaisquer membros do conjunto de caracteres C que não estejam na ISO-646?
Supercat
22

Da The C++ Programming Languageedição especial, página 829

Os caracteres ASCII especiais [, ], {, }, |, e \ocupam as posições de conjuntos de caracteres designados como alfabética pela ISO. Na maioria dos conjuntos de caracteres nacionais europeus ISO-646, essas posições são ocupadas por letras não encontradas no alfabeto inglês.

Um conjunto de trigramas é fornecido para permitir que caracteres nacionais sejam expressos de maneira portátil, usando um conjunto mínimo de caracteres verdadeiramente padrão. Isso pode ser útil para o intercâmbio de programas, mas não facilita a leitura de programas pelas pessoas. Naturalmente, a solução de longo prazo para esse problema é que os programadores de C ++ obtenham equipamentos que suportem tanto a linguagem nativa quanto o C ++. Infelizmente, isso parece inviável para alguns, e a introdução de novos equipamentos pode ser um processo frustrantemente lento.

Roubar
fonte
7
"A introdução de novos equipamentos pode ser um processo frustrantemente lento". Especialmente comparado ao processo rápido e indolor de padronizar os recursos da linguagem de programação.
jforberg
4
Se esse é um argumento para os layouts de teclado, é engraçado que não exista um trigrama, por exemplo, para digitação `, que está faltando no italiano e em vários outros layouts de teclado
badp
15

Eles são para uso em sistemas que não possuem alguns dos caracteres no conjunto de caracteres básicos do C ++. Escusado será dizer que esses sistemas são extremamente raros.

CB Bailey
fonte
2
Isso significa que eu nunca vou usá-los na vida real?
Kirill V. Lyadvinsky
1
em que país você mora? Nem todos os teclados de todos os idiomas possuem as teclas necessárias.
David Thornley
2
Sim, mas talvez você precise estar ciente da existência, caso um cause um resultado inesperado ao ser encontrado, digamos, em uma string literal.
CB Bailey
4
@ David Thornley: A maioria dos sistemas modernos suporta todos os caracteres básicos do C ++, mesmo que não estejam no local convencional ou exijam uma sequência modificadora para digitar. Os trígrafos só precisavam ser mantidos no código-fonte em sistemas em que o caractere não pode realmente ser representado no conjunto de caracteres do sistema. Ainda mantenho que esses sistemas são extremamente raros.
CB Bailey
9

Trígrafos foram propostos para remoção em C ++ 0x. Dito isto, ainda parece haver fortes argumentos a favor deles - veja o documento do comitê C ++ N2910, que discute isso. Aparentemente, o EBCDIC é uma das principais fortalezas onde são necessárias.

Pavel Minaev
fonte
Sim, essa "língua estrangeira"! :-)
Roboprog 5/08/09
Eles realmente não dizem muito, exceto "resultados de uma pesquisa interna de feedback do cliente", mas estão bem. Estou surpreso que EBCDIC ainda está em uso generalizado embora (e que estes sistemas esperar para usar C ++ 0x compiladores)
Peterchen
5

Eu vi trigrafs usados ​​no início dos anos 90 para ajudar a converter programas PL / 1 de um mainframe para serem executados / compilados / depurados em um PC.

Eles estavam envolvidos na edição de PL / I no PC usando um compilador de PL / I para C e queriam que o código funcionasse quando retornados ao mainframe que não suportava chaves. Sugeri que eles pudessem usar macros como

#def BEGIN {    
#def END }  

ou como uma alternativa PL / I mais amigável

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

e se eles realmente quisessem ser extravagantes, poderiam tentar

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

e então o programa pareceria ter sido escrito em Pascal. Eles apenas me olharam engraçado e não falaram comigo pelo resto do dia. Eu não acho que os culpo. :)

O que matou o esforço e não os tri-gráficos, foram as diferenças do sistema de IO entre as plataformas. A abertura de arquivos no PC era muito diferente do mainframe e teria introduzido muitos kludges para manter o mesmo código em execução em ambos.

Kelly S. Francês
fonte
PL / 1 = versão da IBM de C (mais ou menos). Ver o meu comentário: terminais da IBM não têm '{' / '}' chaves :-( Meio difícil de escrever C [++] em um desses, de outro modo.
Roboprog
3

Principalmente porque o padrão C os introduziu em 1989, quando houve problemas com a presença dos caracteres que os trigrafs mapeiam em algumas máquinas. Quando o padrão C ++ foi publicado em 1998, a necessidade de trigramas não era grande. Eles são uma verruga em C; eles são igualmente uma verruga em C ++. Havia uma necessidade deles - especialmente fora do mundo de língua inglesa - e é por isso que foram adicionados ao C.

Jonathan Leffler
fonte
1
Eu sempre suspeitei que a IBM não falava inglês :-)
Roboprog 17/10/2009
3

Alguns teclados europeus não têm (não?) Todos os caracteres de pontuação que os teclados americanos tinham, porque precisavam das teclas para seus caracteres alfabéticos incomuns. Então, por exemplo (inventando isso), o teclado sueco teria um anel A onde estava a chave.

Para acomodar esses usuários, os trigrafs são uma maneira de inserir pontuação usando apenas os caracteres ASCII mais comuns.

Ned Batchelder
fonte
4
Os trígrafos não são realmente sobre entrada de dados (eles tornam o código bastante ilegível), eles são mais sobre sistemas que realmente não têm os caracteres necessários. Se um sistema puder gravar e exibir o caractere - mesmo que seja necessário digitar uma sequência de teclas do tipo trigrama - seria muito mais fácil não reter a sequência do trigrafo na fonte.
CB Bailey
2

Eles estão lá principalmente por razões históricas. Atualmente, os teclados mais modernos para a maioria dos idiomas permitem o acesso a todos esses caracteres, mas isso costumava ser um problema com alguns teclados europeus. É por isso que os trigrafs foram inventados.

Se você não sabe para que servem, não deve usá-los.

No entanto, ainda é bom estar ciente deles, pois você pode usar acidental e involuntariamente um no seu código.

sbi
fonte