Question Qu'est-ce que le C ??! ??! opérateur faire?


J'ai vu une ligne de C qui ressemblait à ceci:

!ErrorHasOccured() ??!??! HandleError();

Il compilé correctement et semble fonctionner correctement. Il semble qu'il vérifie si une erreur s'est produite, et si c'est le cas, il le gère. Mais je ne suis pas vraiment sûr de ce qu'il fait réellement ou comment il le fait. Il semble que le programmeur essaie d'exprimer ses sentiments à propos des erreurs.

Je n'ai jamais vu le ??!??! avant dans n'importe quel langage de programmation, et je ne peux pas trouver de documentation pour cela n'importe où. (Google n'aide pas avec des termes de recherche comme ??!??!). Que fait-il et comment fonctionne l'exemple de code?


1603
2017-10-19 16:56


origine


Réponses:


??! est un trigraph cela se traduit par |. Donc ça dit:

!ErrorHasOccured() || HandleError();

qui, en raison d'un court-circuit, est équivalent à:

if (ErrorHasOccured())
    HandleError();

Gourou de la semaine (traite avec C ++ mais pertinent ici), où j'ai ramassé ceci.

Origine possible des trigraphes ou comme @DwB le souligne dans les commentaires, il est plus probable que EBCDIC soit difficile (encore une fois). Ce discussion sur le forum IBM developerworks semble soutenir cette théorie.

D'ISO / CEI 9899: 1999 §5.2.1.1, note de bas de page 12 (h / t @ Random832):

Les séquences trigraphiques permettent l'entrée de caractères qui ne sont pas définis dans le jeu de codes invariants   décrit dans l'ISO / CEI 646, qui est un sous-ensemble de l'ensemble de codes US ASCII à sept bits.


1319
2017-10-19 16:58



Eh bien, pourquoi cela existe en général est probablement différent de la raison pour laquelle il existe dans votre exemple.

Tout a commencé il y a un demi-siècle avec la réutilisation de terminaux de communication sur papier en tant qu'interface utilisateur. Dans l'ère initiale Unix et C qui était le téléscripteur ASR-33.

Cet appareil était lent (10 cps) et bruyant et moche et sa vue du jeu de caractères ASCII se terminait à 0x5f, donc il n'avait (regardez de près la photo) aucune des clés:

{ | } ~ 

Les trigraphes ont été définis pour résoudre un problème spécifique. L'idée était que les programmes C pouvaient utiliser le sous-ensemble ASCII trouvé sur l'ASR-33 et dans d'autres environnements manquant les valeurs ASCII élevées.

Votre exemple est en réalité deux ??!, chaque sens |, donc le résultat est ||.

Cependant, les gens qui écrivent du code C ont presque par définition un équipement moderne,1 donc ma conjecture est: quelqu'un qui se montre ou qui s'amuse, en laissant une sorte d'oeuf de Pâques dans le code pour vous de trouver.

Cela a bien fonctionné, cela a mené à une question très populaire de SO.

ASR-33 Teletype

Teletype ASR-33


1. D'ailleurs, les trigraphes ont été inventés par le comité ANSI, qui a rencontré après C devient un succès fulgurant, donc aucun code ou codeur C original ne les aurait utilisés.


354
2017-10-19 21:09



C'est un C trigraph. ??! est |, alors ??!??! est l'opérateur ||


140
2017-10-19 16:58



Comme déjà indiqué ??!??! est essentiellement deux trigraphes (??! et ??! encore une fois) mushed ensemble qui est remplacé-traduit à ||, c'est-à-dire Logique OU, par le préprocesseur.

L'image suivante contenant tous les trigraphes devrait aider à désambiguïser les combinaisons trigraphiques alternatives:

enter image description here (Image tirée de C: Un manuel de référence 5e édition)

Donc, un trigraphe qui ressemble ??(??) finira par cartographier [], ??(??)??(??) sera remplacé par [][] et ainsi de suite, vous avez l'idée.

Puisque les trigraphes sont substitués pendant le pré-traitement, vous pouvez utiliser cpp pour avoir une vue de la sortie vous-même, en utilisant une stupide trigr.c programme:

void main(){ const char *s = "??!??!"; } 

et le traiter avec:

cpp -trigraphs trigr.c 

Vous obtiendrez une sortie de console de

void main(){ const char *s = "||"; }

Comme vous pouvez le remarquer, l'option -trigraphs doit être spécifié sinon cpp émettra un avertissement; cela indique comment les trigraphes sont une chose du passé et n'ont pas de valeur moderne autre que de dérouter les gens qui pourraient les rencontrer.


En ce qui concerne la justification de l'introduction des trigraphes, il est plus facile de comprendre Histoire section de ISO/IEC 646:

L'ISO / CEI 646 et son prédécesseur ASCII (ANSI X3.4) approuvaient largement la pratique existante concernant les codages de caractères dans l'industrie des télécommunications.

Comme ASCII n'a pas fourni un nombre de caractères requis pour les langues autres que l'anglais, un certain nombre de variantes nationales ont été faites qui ont remplacé certains caractères moins utilisés avec ceux nécessaires


79
2018-03-25 02:24