Как уже говорилось ??!??!
, по существу , два триграфы ( ??!
и ??!
снова) mushed вместе , которые заменяются переведенный на ||
, то есть логическое ИЛИ , препроцессором.
Следующая таблица, содержащая каждый триграф, должна помочь устранить неоднозначность альтернативных комбинаций триграфов:
Trigraph Replaces
??( [
??) ]
??< {
??> }
??/ \
??' ^
??= #
??! |
??- ~
Источник: C: Справочное руководство 5-е издание
Таким образом, триграф, который выглядит как ??(??)
, в конечном итоге отобразится []
, ??(??)??(??)
будет заменен [][]
и т. Д., Вы получите идею.
Так как триграфы заменяются во время предварительной обработки, вы можете использовать, cpp
чтобы самостоятельно просмотреть вывод, используя глупую trigr.c
программу:
void main(){ const char *s = "??!??!"; }
и обрабатывать его с помощью:
cpp -trigraphs trigr.c
Вы получите консольный вывод
void main(){ const char *s = "||"; }
Как вы можете заметить, опция -trigraphs
должна быть указана, иначе cpp
будет выдано предупреждение; это указывает на то, что триграфы остались в прошлом и не представляют никакой современной ценности, кроме как сбивать с толку людей, которые могут столкнуться с ними .
Что касается обоснования введения триграфов, то лучше понять, рассматривая раздел истории ИСО / МЭК 646 :
ИСО / МЭК 646 и его предшественник ASCII (ANSI X3.4) в значительной степени одобрили существующую практику в отношении кодировки символов в телекоммуникационной отрасли.
Поскольку в ASCII не было указано количество символов, необходимых для языков, отличных от английского, был создан ряд национальных вариантов, которые заменяли некоторые менее используемые символы на нужные .
(акцент мой)
Таким образом, по существу, некоторые необходимые символы (те, для которых существует триграф) были заменены в определенных национальных вариантах. Это приводит к альтернативному представлению с использованием триграфов, состоящих из символов, которые все еще были в других вариантах.
!ErrorHasOccurred() ??!???! HandleError();
собираетесь компилировать? Это??!
???
!
. Доказывает смысл?