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


1 Answers

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 trigraph 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 disponevano di attrezzature moderne, 1 quindi la mia ipotesi è: qualcuno che si esibisce o si diverte, lasciando una specie di uovo di Pasqua nel codice che è possibile trovare.

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

Teletype ASR-33

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

Question

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?




Come già affermato ??!??! sono essenzialmente due trigraphs ( ??! e ??! again again) fusi insieme che vengono sostituiti-tradotto in || , cioè l' OR logico , dal preprocessore.

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

(Immagine tratta da C: A Reference Manual 5th Edition )

Quindi un trigraph che assomigli ??(??) alla fine mapperà a [] , ??(??)??(??) verrà sostituito da [][] e così via, avrai l'idea.

Poiché i trigraph vengono sostituiti durante la pre-elaborazione, è possibile utilizzare cpp per ottenere una vista dell'output da soli, utilizzando un programma silly trigr.c :

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 specificata altrimenti cpp emetterà un avviso; questo indica come i trigrafi siano una cosa del passato e di nessun valore moderno oltre a confondere le persone che potrebbero incontrarli .

Per quanto riguarda la logica alla base dell'introduzione dei trigraph, è meglio compreso guardando la sezione Storia 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 apportate numerose varianti nazionali che sostituivano alcuni caratteri meno utilizzati con quelli necessari .

(sottolineatura mia)

Quindi, in sostanza, alcuni caratteri necessari (quelli per cui esiste un trigrafo) sono stati sostituiti in alcune varianti nazionali. Questo portò alla rappresentazione alternativa usando i trigrafi composti da caratteri che altre varianti avevano ancora in giro.




Related