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


Я видел линию C, которая выглядела так:

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

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

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


1583


источник


Ответы:


??!это триграф это означает |, Так говорится:

!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, который является подмножеством семибитового набора USSCII.


1306



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

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

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

{ | } ~ 

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

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

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

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

ASR-33 Teletype

Телетайп ASR-33


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


344



Это C триграф , ??!является |, так ??!??!является оператором ||


136



Как уже было сказано ??!??!по существу две триграфы ( ??!а также ??!снова), собравшиеся вместе, которые заменяются - переведены на ||, то есть Логический ИЛИ , препроцессором.

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

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 не предоставил ряд символов, необходимых для языков, отличных от английского, был сделан ряд национальных вариантов, которые заменяли некоторые менее используемые персонажи с необходимыми


72