Pregunta ¿Qué hace el C ??! ??! operador hacer?


Vi una línea de C que se veía así:

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

Se compiló correctamente y parece funcionar bien. Parece que está comprobando si se ha producido un error, y si lo tiene, lo maneja. Pero no estoy muy seguro de lo que realmente está haciendo o cómo lo está haciendo. Parece que el programador intenta expresar sus sentimientos sobre los errores.

Nunca he visto el ??!??! antes en cualquier lenguaje de programación, y no puedo encontrar documentación para él en ninguna parte. (Google no ayuda con términos de búsqueda como ??!??!) ¿Qué hace y cómo funciona la muestra del código?


1603
2017-10-19 16:56


origen


Respuestas:


??! es un trigraph eso se traduce a |. Entonces dice:

!ErrorHasOccured() || HandleError();

que, debido a un cortocircuito, es equivalente a:

if (ErrorHasOccured())
    HandleError();

Gurú de la semana (se trata de C ++ pero relevante aquí), donde recogí esto.

Posible origen de los trigrafos o como @DwB señala en los comentarios es más probable debido a que EBCDIC sea difícil (nuevamente). Esta la discusión sobre el tablero de IBM developerworks parece apoyar esa teoría.

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

Las secuencias de trigrafos permiten la entrada de caracteres que no están definidos en el conjunto de códigos invariables como   descrito en ISO / IEC 646, que es un subconjunto del conjunto de códigos ASCII de EE. UU. de siete bits.


1319
2017-10-19 16:58



Bueno, por qué esto existe en general es probablemente diferente de por qué existe en tu ejemplo.

Todo comenzó hace medio siglo con la reutilización de terminales de comunicación en papel como interfaces de usuario de computadora. En la era inicial de Unix y C, ese era el teletipo ASR-33.

Este dispositivo era lento (10 cps) y ruidoso y feo y su vista del conjunto de caracteres ASCII terminaba en 0x5f, por lo que tenía (mira de cerca la foto) ninguna de las teclas:

{ | } ~ 

Los trigrafos se definieron para solucionar un problema específico. La idea era que los programas C podrían usar el subconjunto ASCII que se encuentra en el ASR-33 y en otros entornos que carecen de los altos valores ASCII.

Tu ejemplo es en realidad dos de ??!, cada significado |, entonces el resultado es ||.

Sin embargo, las personas que escriben código C casi por definición tenían equipo moderno,1 así que mi suposición es: alguien mostrando o divirtiéndose, dejando un tipo de huevo de Pascua en el código para que puedas encontrar.

Sin duda funcionó, condujo a una pregunta SO muy popular.

ASR-33 Teletype

Teletipo ASR-33


1. Para el caso, los trigrafos fueron inventados por el comité ANSI, que se reunió por primera vez después C se convirtió en un éxito desbocado, por lo que ninguno de los codificadores originales o codificadores originales los usaría.


354
2017-10-19 21:09



Es un C trigraph. ??! es |, asi que ??!??! es el operador ||


140
2017-10-19 16:58



Como ya se dijo ??!??! es esencialmente dos trigrafos (??! y ??! de nuevo) mezclados que se reemplazan -traducen a ||, es decir, O lógico, por el preprocesador.

La siguiente imagen que contiene todos los trigrafos debería ayudar a eliminar la ambigüedad de las combinaciones de trigrafos alternativos:

enter image description here (Imagen tomada de C: A Manual de referencia 5a edición)

Entonces un trigraph que se parece ??(??) eventualmente se asignará a [], ??(??)??(??) será reemplazado por [][] y así sucesivamente, entiendes la idea.

Como los trigrafos se sustituyen durante el preprocesamiento, puede usar cpp para obtener una vista de la salida usted mismo, usando un tonto trigr.c programa:

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

y procesarlo con:

cpp -trigraphs trigr.c 

Obtendrás una salida de consola de

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

Como puede notar, la opción -trigraphs debe ser especificado o bien cpp emitirá una advertencia; esto indica como los trigrafos son una cosa del pasado y de ningún valor moderno que no sea confundir a las personas que podrían toparse con ellos.


En cuanto a la razón de ser de la introducción de los trigrafos, se comprende mejor cuando se mira el Historia Sección de ISO/IEC 646:

ISO / IEC 646 y su predecesor ASCII (ANSI X3.4) respaldaron ampliamente la práctica existente con respecto a las codificaciones de caracteres en la industria de las telecomunicaciones.

Como ASCII no proporcionó una cantidad de caracteres necesarios para idiomas distintos del inglés, se hicieron varias variantes nacionales que sustituyeron algunos caracteres menos utilizados con los necesarios


79
2018-03-25 02:24