Что делает C! оператор?

я увидел строку C, которая выглядела так:

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

он скомпилирован правильно и, кажется, работает нормально. Похоже, он проверяет, произошла ли ошибка, и если да, он обрабатывает ее. Но я не совсем уверен, что он на самом деле делает или как он это делает. Похоже, программист пытается выразить свои чувства по поводу ошибок.

Я никогда не видел ??!??! раньше на любом языке программирования, и я не могу найти документацию для него нигде. (Погуглить не помогает с поисковыми терминами, такими как ??!??!). Что он делает и как работает образец кода?

4 ответов


??! это trigraph что означает |. Вот оно и говорит:

!ErrorHasOccured() || HandleError();

что, из-за короткого замыкания, составляет:

if (ErrorHasOccured())
    HandleError();

гуру недели (имеет дело с C++ , но актуально здесь), где я взял это.

возможное происхождение триграфов или, как указывает @DwB в комментариях, это более вероятно из-за того, что EBCDIC сложно (снова). этой обсуждение IBM совет developerworks, похоже, поддерживает эту теорию.

из ISO / IEC 9899: 1999 §5.2.1.1, сноска 12 (h / t @Random832):

последовательности триграфов позволяют вводить символы, которые не определены в Инвариантном наборе кода как описано в ISO / IEC 646, который является подмножеством семиразрядного набора кодов ASCII в США.


Ну, почему это существует вообще, вероятно, отличается от того, почему он существует в вашем примере.

все началось полвека назад с перепрофилирования печатных коммуникационных терминалов в качестве компьютерных пользовательских интерфейсов. В начальную эпоху Unix и C это был телетайп ASR-33.

Это устройство было медленным (10 cps) и шумным и уродливым, и его вид набора символов ASCII заканчивался на 0x5f, поэтому у него не было (посмотрите внимательно на рис) ни одного из ключи:

{ | } ~ 

в триграфов были определены для устранения конкретной проблемы. Идея заключалась в том, что программы C могли использовать подмножество ASCII, найденное на ASR-33, а в других средах отсутствовали высокие значения ASCII.

ваш пример на самом деле два ??!, что |, Так что в результате ||.

однако люди, пишущие код C почти по определению, имели современное оборудование,1 так что мое предположение:кто-то хвастается или забавляется, оставив своего рода пасхальное яйцо в коде для вас найти.

это конечно сработало, это привело к дико популярному вопросу SO.

ASR-33 Teletype

телетайп ASR-33


1. Если уж на то пошло, триграфы были изобретены комитетом Анси, который впервые собрался после C стать a неудавшийся успех, поэтому ни один из исходных кодов C или кодеров не использовал бы их.

Это C trigraph. ??! is |, so ??!??! оператор ||


как уже сказано ??!??! - это, по существу, два триграфов (??! и ??! снова) смешанные вместе, которые заменяются-переводится на ||, Я.e логическое или, препроцессором.

следующее изображение, содержащее все триграфы, должно помочь устранить неоднозначность альтернативных комбинаций триграфов:

enter image description here (Изображение взято из 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 не предоставил количество символов, необходимых для других языков, кроме английского,был сделан ряд национальных вариантов, которые заменили некоторые менее используемые символы необходимыми одни!--19-->.

(выделено мной)

таким образом, по сути, некоторые необходимые символы (те, для которых существует триграф) были заменены в некоторых национальных вариантах. Это приводит к альтернативному представлению с использованием триграфов, состоящих из символов, которые все еще были вокруг других вариантов.