Como já foi dito, ??!??!
são essencialmente dois trigramas ( ??!
e ??!
novamente) misturados que são substituídos - traduzidos para ||
, ou seja, o OR lógico , pelo pré-processador.
A tabela a seguir, contendo todos os trigramas, deve ajudar a desambiguar combinações alternativas de trigramas:
Trigraph Replaces
??( [
??) ]
??< {
??> }
??/ \
??' ^
??= #
??! |
??- ~
Fonte: C: Um Manual de Referência 5ª Edição
Assim, um trigrama que pareça ??(??)
eventualmente será mapeado para []
, ??(??)??(??)
será substituído [][]
e assim por diante, você entenderá.
Como os trigrafs são substituídos durante o pré-processamento, você pode usar cpp
para obter uma visão da saída, usando um trigr.c
programa bobo :
void main(){ const char *s = "??!??!"; }
e processando-o com:
cpp -trigraphs trigr.c
Você obterá uma saída do console de
void main(){ const char *s = "||"; }
Como você pode perceber, a opção -trigraphs
deve ser especificada ou então cpp
emitirá um aviso; isso indica como os trigramas são coisa do passado e não têm valor moderno além de confundir pessoas que possam esbarrar neles .
Quanto à justificativa por trás da introdução dos trigramas, é melhor compreendida ao examinar a seção de histórico da ISO / IEC 646 :
A ISO / IEC 646 e seu antecessor ASCII (ANSI X3.4) endossaram amplamente as práticas existentes em relação a codificações de caracteres no setor de telecomunicações.
Como o ASCII não forneceu um número de caracteres necessários para outros idiomas além do inglês, foram feitas várias variantes nacionais que substituíram alguns caracteres menos utilizados pelos necessários .
(ênfase minha)
Portanto, em essência, alguns caracteres necessários (aqueles para os quais existe um trigrama) foram substituídos em certas variantes nacionais. Isso leva à representação alternativa usando trigramas compostos por caracteres que outras variantes ainda possuíam.
!ErrorHasOccurred() ??!???! HandleError();
compilar? É isso??!
???
!
. Prova o ponto?