Что делает C??!??! оператор?
Я видел строку C, которая выглядела так:
!ErrorHasOccured() ??!??! HandleError();
Он правильно скомпилирован и, кажется, работает нормально. Кажется, что он проверяет, произошла ли ошибка, и если она есть, она обрабатывает ее. Но я не совсем уверен, что он на самом деле делает или как он это делает. Это похоже на то, что программист пытается выразить свои чувства по поводу ошибок.
Я никогда не видел ??!??!
раньше на любом языке программирования, и я нигде не могу найти документацию. (Google не помогает с поисковыми запросами типа ??!??!
). Что он делает и как работает образец кода?
Ответы
Ответ 1
??!
является trigraph, который переводится в |
. Поэтому он говорит:
!ErrorHasOccured() || HandleError();
который из-за короткого замыкания эквивалентен:
if (ErrorHasOccured())
HandleError();
Гуру недели (имеет дело с С++, но актуальным здесь), где я взял это.
Возможное происхождение триграфов или как @DwB указывает на комментарии, которые, скорее всего, из-за сложности EBCDIC (опять же). Эта дискуссия на панели разработчиков developerWorks, похоже, поддерживает эту теорию.
Из ISO/IEC 9899: 1999 §5.2.1.1, сноска 12 (h/t @Random832):
Триграфные последовательности позволяют вводить символы, которые не определены в Инвариантном коде, как описанный в ISO/IEC 646, который является подмножеством семибитового кода USSCII.
Ответ 2
Хорошо, почему это вообще существует, вероятно, отличается от того, почему оно существует в вашем примере.
Все началось полвека назад с перепродажи печатных терминалов связи в качестве пользовательских интерфейсов пользователя. В начальный период Unix и C, который был Teletype ASR-33.
Это устройство было медленным (10 cps), шумным и уродливым, и его вид набора символов ASCII закончился 0x5f, поэтому он (внимательно посмотрите на рис.) ни один из клавиш:
{ | } ~
Триграфы были определены для устранения конкретной проблемы. Идея заключалась в том, что C-программы могут использовать подмножество ASCII, найденное на ASR-33, и в других средах, не имеющих высоких значений ASCII.
Ваш пример на самом деле два из ??!
, каждый из которых означает |
, поэтому результат ||
.
Однако люди, пишущие код C почти по определению, имели современное оборудование, 1 поэтому я предполагаю, что кто-то демонстрирует или развлекает себя, оставляя в коде код своего пасхального яйца.
Это наверняка сработало, это привело к чрезвычайно популярному вопросу SO.
SUP > 1. В этом отношении триграфы были изобретены комитетом ANSI, который впервые встретился после того, как C стал безудержным успехом, поэтому ни один из исходных кодов C или кодеров не использовал бы их.
Ответ 3
Это c trigraph. ??!
|
, поэтому ??!??!
- оператор ||
Ответ 4
Как уже говорилось, ??!??!
представляет собой по существу два триграммы (??!
и ??!
снова) которые заменяются - переводятся на ||
, т.е. Логическое ИЛИ, препроцессором.
Следующее изображение, содержащее все триграфы, должно помочь устранить неоднозначные комбинации альтернативных триграмм:
(Изображение взято из C: Справочное руководство 5-го издания)
Итак, триграф, который выглядит как ??(??)
, в конечном итоге будет отображаться на []
, ??(??)??(??)
будет заменен на [][]
и т.д., вы получите эту идею.
Поскольку триграфы заменяются во время предварительной обработки, вы можете использовать cpp
, чтобы получить представление о выходе самостоятельно, используя глупую программу trigr.c
void main(){ const char *s = "??!??!"; }
и обрабатывая его с помощью
cpp -trigraphs trigr.c
Вы получите консольный вывод
void main(){ const char *s = "||"; }
Как вы можете заметить, необходимо указать опцию -trigraphs
, иначе cpp
выдаст предупреждение; это указывает на то, как триграфы ушли в прошлое и не имеют современной ценности, кроме путаницы людей, которые могут столкнуться с ними.
Что касается обоснования введения триграфов, то это лучше понять при просмотре раздела истории ISO/IEC 646
:
ISO/IEC 646 и его предшественник ASCII (ANSI X3.4) в значительной степени одобрили существующую практику кодирования символов в телекоммуникационной отрасли.
Поскольку ASCII не предоставил несколько символов, необходимых для языков, отличных от английского, было сделано несколько национальных вариантов, которые заменяли некоторые менее используемые символы с необходимыми.
(акцент мой)
Итак, по сути, некоторые необходимые персонажи (те, для которых существует триграф) были заменены в некоторых национальных вариантах. Это приводит к альтернативному представлению с использованием триграфов, состоящих из символов, которые все еще имели другие варианты.