operators bitwise - Cosa fa la C ??! ??! operatore?




xor (5)

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 avevano un'attrezzatura moderna, 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.

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.


??! è 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 è pertinente qui), dove ho scelto questo.

Possibile origine dei trigrafi o come @DwB indica nei commenti è più probabile che a causa di EBCDIC sia difficile (di nuovo). This discussione sulla scheda IBM developerworks sembra supportare questa teoria.

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

Le sequenze del trigramma consentono l'immissione 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.


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


Sì, è stato added nella versione 2.5.
La sintassi è:

a if condition else b

Viene valutata la prima condition , quindi a o b viene restituito in base al valore Boolean della condition
Se la condition restituisce True, viene restituito, altrimenti viene restituito b .

Per esempio:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

Nota che i condizionali sono un'espressione , non un'affermazione . Ciò significa che non è possibile utilizzare assegnazioni o pass o altre dichiarazioni in modo condizionale:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

In tal caso, devi usare una normale istruzione if invece di una condizionale.

Tieni presente che è sfigurato da alcuni Pythonistas per diversi motivi:

  • L'ordine degli argomenti è diverso da molti altri linguaggi (come C, Ruby, Java, ecc.), Che possono portare a bug quando le persone che non hanno familiarità con il comportamento "sorprendente" di Python lo usano (potrebbero invertire l'ordine).
  • Alcuni lo trovano "ingombrante", poiché va contro il normale flusso del pensiero (pensando prima alla condizione e poi agli effetti).
  • Ragioni stilistiche

Se hai difficoltà a ricordare l'ordine, ricorda che se lo leggi ad alta voce, dici (quasi) cosa intendi. Ad esempio, x = 4 if b > 8 else 9 viene letto ad alta voce come x will be 4 if b is greater than 8 otherwise 9 .

Documentazione ufficiale:







c operators trigraphs