Objectif des séquences Trigraph en C ++?

128

Selon la norme C ++ '03 2.3 / 1:

Avant tout autre traitement, chaque occurrence de l'une des séquences suivantes de trois caractères («séquences de trigraphes») est remplacée par le caractère unique indiqué dans le tableau 1.

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

Dans la vraie vie, cela signifie que le code printf( "What??!\n" );entraînera une impression What|car ??!c'est une séquence de trigraphe qui est remplacée par le |caractère.

Ma question est à quoi sert les trigraphes? Y a-t-il un avantage pratique à utiliser les trigraphes?

UPD : Dans les réponses, il a été mentionné que certains claviers européens n'ont pas tous les caractères de ponctuation, donc les programmeurs non américains doivent utiliser des trigraphes dans la vie quotidienne?

UPD2 : Visual Studio 2010 a la prise en charge des trigraphes désactivée par défaut.

Kirill V. Lyadvinsky
la source
Une partie de la ponctuation est plus difficile à atteindre sur les claviers européens (au point que certains programmeurs utilisent la disposition américaine pour taper plus rapidement).
peterchen
2
Il peut arriver que certains terminaux et / ou virtualisations ne vous permettent pas d'accéder facilement à certains personnages. D'après mon expérience, le principal délinquant est le tilde.
Francesco
1
en tapant ceci sur mon clavier DE-deadkeys, # est une touche à côté de return, \ est "AltGr" + "ß" (à côté de 0), ^ est "^" + "^" (à cause des deadkeys; à côté de 1) , [est "AltGr" + "8",] est "AltGr" + "9", | est "AltGr" + "<", {est "AltGr" + "7",} est "AltGr" + "0", et ~ est "~" + "~" (à cause des deadkeys, juste au-dessus de #). donc pas vraiment grand-chose. mes doigts sont comme taper ces combinaisons tout seuls :-D
puce
1
J'ai pensé qu'il était normal d'avoir deux configurations de clavier et de les changer en fonction du travail que je fais sur l'ordinateur. C'est la méthode courante dans la région d'Europe centrale. C'est assez effrayant d'utiliser ces trigraphes. Je voterais pour supprimer cela de la norme.
VX
1
@VX Vous avez votre souhait!
graham.reeds

Réponses:

98

Cette question (sur les digraphes étroitement liés) a la réponse.

Cela se résume au fait que le jeu de caractères ISO 646 ne contient pas tous les caractères de la syntaxe C, il existe donc des systèmes avec des claviers et des écrans qui ne peuvent pas gérer les caractères (même si j'imagine que ceux-ci sont assez rares aujourd'hui).

En général, vous n'avez pas besoin de les utiliser, mais vous devez les connaître pour exactement le problème que vous avez rencontré. Les trigraphes sont la raison pour laquelle le ?caractère « » a une séquence d'échappement:

'\?'

Vous pouvez donc éviter votre exemple de problème de deux manières:

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

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

Mais vous devez vous souvenir lorsque vous tapez les deux "?" caractères auxquels vous pourriez commencer un trigraphe (et ce n'est certainement jamais quelque chose auquel je pense).

En pratique, les trigraphes et les digraphes sont quelque chose qui ne me préoccupe pas du tout au quotidien. Mais vous devez en être conscient car une fois tous les deux ans, vous rencontrerez un bug qui leur est lié (et vous passerez le reste de la journée à maudire leur existence). Ce serait bien si les compilateurs pouvaient être configurés pour avertir (ou faire une erreur) quand il tombe sur un trigraphe ou un digraphe, afin que je puisse savoir que j'ai quelque chose que je devrais traiter sciemment.

Et juste pour être complet, les digraphes sont beaucoup moins dangereux car ils sont traités comme des jetons, donc un digraphe à l'intérieur d'une chaîne littérale ne sera pas interprété comme un digraphe.

Pour une bonne éducation sur divers amusements avec la ponctuation dans les programmes C / C ++ (y compris un bogue de trigraphe qui me ferait définitivement arracher les cheveux), jetez un œil à l'article GOTW # 86 de Herb Sutter .


Addenda:

Il semble que GCC ne traitera pas (et en avertira) les trigraphes par défaut. Certains autres compilateurs ont des options pour désactiver la prise en charge des trigraphes (IBM par exemple). Microsoft a commencé à prendre en charge un avertissement (C4837) dans VS2008 qui doit être explicitement activé (en utilisant -Wall ou quelque chose).

Michael Burr
la source
La compatibilité avec C est la seule raison? Est-ce possible de les rencontrer dans des programmes C ++ modernes?
Kirill V. Lyadvinsky
Oui, C ++ prend également en charge les trigraphes et les digraphes.
Michael Burr
4
Si je me souviens bien, au moins un compilateur que j'ai utilisé (g ++?) Nécessite une option de ligne de commande explicite avant que trigraph et / ou digraph ne soit traduit, sinon un avertissement est donné mais aucune substitution.
KTC
1
@ Jla3ep - Personnellement, je n'ai jamais eu besoin de trigraphes, mais malheureusement, les compilateurs traiteront le code avec eux, vous devez donc en être conscient (pour éviter toute utilisation accidentelle). De plus, si vous obtenez du code ailleurs, vous risquez de rencontrer leur utilisation intentionnelle, mais ce serait extrêmement inhabituel. Je pense que j'ai rencontré des trigraphes intentionnellement utilisés une fois en plus de 20 ans (c'était du code pour un mainframe IBM).
Michael Burr
1
Cela ne m'énerve vraiment que lorsque les trigraphes sont développés dans les commentaires pour faire des choses surprenantes.
Joshua
23

Les enfants aujourd'hui! :-)

Oui, équipement étranger, tel qu'un terminal IBM 3270. Le 3270 n'a, si je me souviens, pas de bretelles! Si vous vouliez écrire C sur un IBM mini / mainframe, vous deviez utiliser les trigraphes misérables pour chaque limite de bloc. Heureusement, je n'ai eu qu'à écrire des logiciels en C pour émuler certaines installations de mini-ordinateurs IBM, pas vraiment d'écrire des logiciels C sur le System / 36.

Regardez à côté de la touche "P":

clavier

Hmmm. Dur à dire. Il y a un bouton supplémentaire à côté de "retour chariot", et je pourrais l'avoir à l'envers: c'était peut-être la paire "[" / "]" qui manquait. En tout cas, ce clavier vous causerait du chagrin si vous deviez écrire C.

De plus, ces terminaux affichent EBCDIC, le jeu de caractères mainframe "natif" d'IBM, et non ASCII (merci, Pavel Minaev, pour le rappel).

D'un autre côté, comme le dit le guide GNU C: "Vous n'avez pas besoin de ces lésions cérébrales." Le compilateur gcc laisse cette "fonctionnalité" désactivée par défaut.

Roboprog
la source
1
Il y a un bouton de réinitialisation sur le clavier. C'est génial! Étrange qui a attiré mon attention en premier.
l46kok du
11
Quiconque souhaite utiliser C ++ 17 sur une machine EBCDIC doit être emprisonné pour nécrophilie.
SF.
À moins d' une plate - forme n'a pas de caractère à tous les autres que ceux ISO646, ne pouvait pas tout ce qui peut être fait avec trigraphes, faire en exigeant que chaque mise en œuvre définissent soit une barre oblique inverse ou bien un caractère qui ne sont pas dans le caractère C ensemble comme "meta", remplacer toutes les références à la barre oblique inverse dans la norme par "meta", et ajouter des échappements anti-slash / meta pour tous les membres du jeu de caractères C qui ne sont pas dans ISO-646?
supercat du
22

À partir de The C++ Programming Languagel'édition spéciale, page 829

Les caractères spéciaux ASCII [, ], {, }, |et\ occupent des positions de jeu de caractères désignés comme alphabétique par l' ISO. Dans la plupart des jeux de caractères nationaux européens ISO-646, ces positions sont occupées par des lettres qui ne se trouvent pas dans l'alphabet anglais.

Un ensemble de trigraphes est fourni pour permettre aux caractères nationaux d'être exprimés de manière portable en utilisant un jeu de caractères minimal vraiment standard. Cela peut être utile pour l'échange de programmes, mais cela ne facilite pas la lecture des programmes. Naturellement, la solution à long terme à ce problème est que les programmeurs C ++ obtiennent un équipement qui prend en charge à la fois leur langage natif et C ++. Malheureusement, cela semble irréalisable pour certains, et l'introduction de nouveaux équipements peut être un processus extrêmement lent.

Rob
la source
8
"L'introduction de nouveaux équipements peut être un processus extrêmement lent". Surtout par rapport au processus rapide et indolore de normalisation des fonctionnalités du langage de programmation.
jforberg
4
S'il s'agit d'un kludge pour les dispositions de clavier, alors c'est drôle qu'il n'y ait pas de trigraphe, par exemple pour la saisie `, qui manque à l'italien et à plusieurs autres dispositions de clavier
badp
15

Ils sont destinés à être utilisés sur des systèmes qui ne contiennent pas certains des caractères du jeu de caractères de base de C ++. Il va sans dire que de tels systèmes sont extrêmement rares.

CB Bailey
la source
2
Est-ce que ça veut dire que je ne les utiliserai jamais dans la vraie vie?
Kirill V. Lyadvinsky
1
Dans quel pays habites-tu? Tous les claviers pour toutes les langues ne disposent pas des touches nécessaires.
David Thornley
2
Oui, mais vous devrez peut-être être conscient de son existence au cas où l'un d'entre eux provoquerait un résultat inattendu lorsqu'il serait détecté, par exemple, dans une chaîne littérale.
CB Bailey
4
@David Thornley: La plupart des systèmes modernes prennent en charge tous les caractères de base de C ++ même s'ils ne sont pas à la place conventionnelle ou nécessitent une séquence de modificateurs pour taper. Les trigraphes ne devaient être conservées dans le code source que sur les systèmes où le caractère ne peut pas réellement être représenté dans le jeu de caractères système. Je maintiens toujours que de tels systèmes sont extrêmement rares.
CB Bailey
9

Les trigraphes ont été proposés pour la suppression dans C ++ 0x. Cela dit, il semble y avoir encore de solides arguments pour les soutenir - voir le document du comité C ++ N2910 qui en discute. Apparemment, EBCDIC est un bastion majeur où ils sont nécessaires.

Pavel Minaev
la source
Oui, cette "langue étrangère"! :-)
Roboprog
Ils ne disent pas grand chose sauf "les résultats d'une enquête interne sur les commentaires des clients", mais bon. Je suis surpris que EBCDIC soit toujours largement utilisé (et que ces systèmes s'attendent à utiliser des compilateurs C ++ 0x)
peterchen
5

J'ai vu des trigraphes utilisés au début des années 90 pour aider à convertir des programmes PL / 1 d'un mainframe à exécuter / compiler / déboguer sur un PC.

Ils essayaient de modifier PL / I sur le PC en utilisant un compilateur PL / I vers C et ils voulaient que le code fonctionne une fois déplacé vers le mainframe qui ne supportait pas les accolades. J'ai suggéré qu'ils pourraient utiliser des macros comme

#def BEGIN {    
#def END }  

ou comme alternative PL / I plus conviviale

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

et s'ils voulaient vraiment avoir de la fantaisie, ils pourraient essayer

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

et alors le programme aurait l'air d'avoir été écrit en Pascal. Ils m'ont juste regardé bizarrement et n'ont pas voulu me parler pour le reste de la journée. Je ne pense pas que je les blâme. :)

Ce qui a tué l'effort et non les tri-graphes, ce sont les différences de système IO entre les plates-formes. L'ouverture de fichiers sur le PC était tellement différente de celle du mainframe qu'elle aurait introduit beaucoup trop de kludges pour que le même code fonctionne sur les deux.

Kelly S.Français
la source
PL / 1 = version IBM de C (plus ou moins). Voir mon commentaire: les terminaux IBM n'ont pas de clés '{' / '}' :-( Genre de difficile à écrire C [++] sur l'un d'entre eux, sinon.
Roboprog
3

Principalement parce que le standard C les a introduits en 1989, quand il y avait des problèmes avec la présence des caractères auxquels les trigraphes mappaient sur certaines machines. Au moment où la norme C ++ a été publiée en 1998, le besoin de trigraphes n'était pas grand. Ils sont une verrue sur C; ils sont tout autant une verrue sur C ++. Il y avait un besoin pour eux - surtout en dehors du monde anglophone - c'est pourquoi ils ont été ajoutés à C.

Jonathan Leffler
la source
1
J'ai toujours soupçonné qu'IBM ne parlait pas anglais :-)
Roboprog
3

Certains claviers européens n'ont pas (n'a pas?) Tous les caractères de ponctuation que les claviers américains avaient, car ils avaient besoin des touches pour leurs caractères alphabétiques inhabituels. Ainsi, par exemple (en créant cela), le clavier suédois aurait un anneau en A là où se trouvait l'accolade.

Pour s'adapter à ces utilisateurs, les trigraphes sont un moyen de saisir la ponctuation en utilisant uniquement les caractères ASCII les plus courants.

Ned Batchelder
la source
4
Les trigraphes ne concernent pas vraiment la saisie de données (ils rendent le code assez illisible), ils concernent davantage des systèmes qui n'ont pas réellement les caractères requis. Si un système peut enregistrer et afficher le caractère - même si un trigraphe comme une séquence de touches doit être saisi - il serait beaucoup plus facile de ne pas conserver la séquence de trigraphe dans la source.
CB Bailey
2

Ils sont là principalement pour des raisons historiques. De nos jours, la plupart des claviers modernes pour la plupart des langues permettent d'accéder à tous ces caractères, mais cela posait autrefois un problème avec certains claviers européens. C'est pourquoi les trigraphes ont été inventés.

Si vous ne savez pas à quoi ils servent, vous ne devriez pas les utiliser.

Cependant, il est toujours bon d'en être conscient, car vous pourriez en utiliser un accidentellement et involontairement dans votre code.

sbi
la source