relacionales operadores logicos lenguaje jerarquia asignacion aritmeticos c operators trigraphs

operadores - ¿Qué hace el C ??! ??! operador hacer?



operadores logicos en lenguaje c (4)

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

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

Se compiló correctamente y parece funcionar bien. Parece que está verificando si ha ocurrido un error, y si lo ha hecho, lo maneja. Pero no estoy realmente seguro de lo que realmente está haciendo o cómo lo está haciendo. Parece que el programador está tratando de expresar sus sentimientos acerca de los errores.

Nunca he visto el ??!??! antes en cualquier lenguaje de programación, y no puedo encontrar documentación para ello en ningún lugar. (Google no ayuda con los términos de búsqueda como ??!??! ). ¿Qué hace y cómo funciona el ejemplo de código?


Bueno, por qué esto existe en general es probablemente diferente a por qué existe en su ejemplo.

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

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

{ | } ~

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

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

Sin embargo, las personas que escribían el código C casi por definición tenían equipo moderno, 1 así que supongo: alguien que se muestra o se divierte, dejando una especie de huevo de Pascua en el código para que lo encuentres.

Seguro que funcionó, condujo a una pregunta SO muy popular.

Teletipo ASR-33

1. En ese caso, los trigraphs fueron inventados por el comité ANSI, que se reunió por primera vez después de que C se convirtió en un gran éxito, por lo que ninguno de los codificadores o el código C original los habría utilizado.

Como ya se ha dicho ??!??! es esencialmente dos trigraphs ( ??! y ??! otra vez) agrupados que se reemplazan-traducen a || , es decir, el OR lógico , por el preprocesador.

La siguiente imagen que contiene todos los trigraphs debería ayudar a desambiguar combinaciones alternativas de trigraph:

(Imagen tomada de C: A Manual de referencia 5ª edición )

Así que un trigraph que se parece a ??(??) eventualmente se asignará a [] , ??(??)??(??) se reemplazará por [][] y así sucesivamente, se obtiene la idea.

Como los trigraphs se sustituyen durante el preproceso, puede usar cpp para obtener una vista de la salida, utilizando un programa trigr.c tonto:

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

y procesándolo con:

cpp -trigraphs trigr.c

Obtendrás una salida de consola de

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

Como puede observar, la opción -trigraphs debe estar especificada o de lo contrario, cpp emitirá una advertencia; esto indica que los trigraphs son cosa del pasado y que no tienen valor moderno, aparte de confundir a las personas que podrían toparse con ellos .

En cuanto a la razón detrás de la introducción de trigraphs, se entiende mejor al mirar la sección de Historia de ISO/IEC 646 :

ISO / IEC 646 y su antecesor 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 otros idiomas además del inglés, se hicieron varias variantes nacionales que sustituyeron a algunos caracteres menos usados ​​con los necesarios .

(énfasis mío)

Entonces, en esencia, algunos caracteres necesarios (aquellos para los cuales existe un trigraph) fueron reemplazados en ciertas variantes nacionales. Esto condujo a la representación alternativa utilizando trigráficos compuestos por caracteres que aún tenían otras variantes.


Es un trigraph C ??! es | , entonces ??!??! es el operador ||


??! es un trigraph que se traduce a | . Eso dice:

!ErrorHasOccured() || HandleError();

el cual, por cortocircuito, es equivalente a:

if (ErrorHasOccured()) HandleError();

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

Posible origen de trigraphs o como @DwB señala en los comentarios, es más probable que EBCDIC sea difícil (otra vez). This discusión en el tablero de IBM developerworks parece apoyar esa teoría.

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

Las secuencias de trigraph permiten la entrada de caracteres que no están definidos en el Conjunto de códigos invariantes como se describe en ISO / IEC 646, que es un subconjunto del conjunto de códigos ASCII de EE. UU. De siete bits.