Domanda Cosa fa la C ??! ??! operatore?


Ho visto una riga di C simile a questa:

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

Ha compilato correttamente e sembra funzionare bene. Sembra che stia controllando se si è verificato un errore e se lo ha, lo gestisce. Ma non sono sicuro di cosa stia effettivamente facendo o di come lo sta facendo. Sembra che il programmatore stia cercando di esprimere i propri sentimenti riguardo agli errori.

Non ho mai visto il ??!??! prima in qualsiasi linguaggio di programmazione, e non trovo documentazione per esso ovunque. (Google non aiuta con termini di ricerca come ??!??!). Che cosa fa e come funziona il codice di esempio?


1603
2017-10-19 16:56


origine


risposte:


??! è un trigraph che si traduce in |. Quindi dice:

!ErrorHasOccured() || HandleError();

che, a causa del cortocircuito, equivale a:

if (ErrorHasOccured())
    HandleError();

Guru della settimana (si occupa di C ++ ma rilevante qui), dove ho raccolto questo.

Possibile origine dei trigrafi o come @DwB sottolinea nei commenti è più probabile che EBCDIC sia difficile (di nuovo). Questo la discussione sulla scheda degli sviluppatori di IBM sembra supportare questa teoria.

Da ISO / IEC 9899: 1999 §5.2.1.1, nota 12 (h / t @ Random832):

Le sequenze del trigramma consentono l'inserimento di caratteri che non sono definiti nel set di codici invarianti come   descritto in ISO / IEC 646, che è un sottoinsieme del set di codici ASCII US a sette bit.


1319
2017-10-19 16:58



Bene, perché questo in generale è probabilmente diverso dal perché esiste nel tuo esempio.

Tutto iniziò mezzo secolo fa con la riutilizzazione di terminali di comunicazione cartacei come interfacce utente di computer. Nell'era iniziale di Unix e C era il Teletype ASR-33.

Questo dispositivo era lento (10 cps) e rumoroso e brutto e la sua visualizzazione del set di caratteri ASCII finiva a 0x5f, quindi aveva (guarda attentamente la foto) nessuno dei tasti:

{ | } ~ 

I trigrafi sono stati definiti per risolvere un problema specifico. L'idea era che i programmi C potessero usare il sottoinsieme ASCII trovato sull'ASR-33 e in altri ambienti che mancano i valori ASCII alti.

Il tuo esempio è in realtà due di ??!, ogni significato |, quindi il risultato è ||.

Tuttavia, le persone che scrivono il codice C quasi per definizione avevano attrezzature moderne,1 quindi la mia ipotesi è: qualcuno che si esibisce o si diverte, lasciando una specie di uovo di Pasqua nel codice che devi trovare.

Di sicuro ha funzionato, ha portato a una domanda SO incredibilmente popolare.

ASR-33 Teletype

Teletype ASR-33


1. Del resto, i trigrafi sono stati inventati dal comitato ANSI, che si è incontrato per la prima volta dopo C diventare un successo in fuga, quindi nessuno del codice C o dei programmatori originali li avrebbe usati.


354
2017-10-19 21:09



È un C trigraph. ??! è |, così ??!??! è l'operatore ||


140
2017-10-19 16:58



Come già affermato ??!??! è essenzialmente due trigraph (??! e ??! di nuovo) fusi insieme che vengono sostituiti, tradotti in ||, io il OR logico, dal preprocessore.

L'immagine seguente contenente tutti i trigrafi dovrebbe aiutare a chiarire le combinazioni di trigraph alternate:

enter image description here (Immagine presa da C: A Reference Manual 5th Edition)

Quindi un trigramma che sembra ??(??) alla fine verrà mappato a [], ??(??)??(??) verrà sostituito da [][] e così via, hai avuto l'idea.

Poiché i trigrafi sono sostituiti durante la pre-elaborazione, è possibile utilizzarli cpp per avere una visione dell'output, usando uno sciocco trigr.c programma:

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

ed elaborandolo con:

cpp -trigraphs trigr.c 

Riceverai un output in console di

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

Come puoi notare, l'opzione -trigraphs deve essere specificato o altro cpp emetterà un avvertimento; questo indica come i trigrafi sono una cosa del passato e di nessun valore moderno se non quelli che confondono chi potrebbe incontrarli.


Per quanto riguarda la logica alla base dell'introduzione dei trigrafi, è meglio capire quando si guarda il Storia sezione di ISO/IEC 646:

ISO / IEC 646 e il suo predecessore ASCII (ANSI X3.4) hanno ampiamente sostenuto la pratica esistente per quanto riguarda le codifiche dei caratteri nel settore delle telecomunicazioni.

Poiché ASCII non forniva un numero di caratteri necessario per le lingue diverse dall'inglese, sono state fatte diverse varianti nazionali che sostituivano alcuni personaggi meno usati con quelli necessari


79
2018-03-25 02:24