При чем тут С ??! ??! оператор делает?

1527

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

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

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

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

  • 165
    выражайте свои эмоции иначе, не используйте триграфы, пишите код, понятный людям
  • 37
    @PeterOlson, как вы ожидаете !ErrorHasOccurred() ??!???! HandleError(); Скомпилировать? Это ??! ??? ! , Доказывает смысл?
Показать ещё 9 комментариев
Теги:
operators

4 ответа

1278
Лучший ответ

??! является 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.

  • 323
    Изначально триграфы были нужны в том случае, если на клавиатуре не было, например, «|» условное обозначение. Здесь это либо умышленно раздражает программиста, либо какая-то странная «особенность» редактора
  • 0
    Так что он полагается на || короткое замыкание или что-то?
Показать ещё 20 комментариев
284

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

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

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

{ | } ~ 

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

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

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

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

Изображение 4789

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

  • 12
    Это не единственный случай отсутствия символов в клавиатуре и наборе символов. Commodore 64, вероятно, будет более знакомым многим людям в возрасте 30 лет и старше - отображаемым наборам символов не хватает фигурных скобок (и, вероятно, столбца и тильды тоже) - в этом случае, поскольку «ASCII» не был ASCII , В ECMA-6 (почти всегда называемой ASCII, но не US-ASCII) было 18 специфичных для региона кодов, но я не знаю, какими они были. Одно могу сказать точно - в британском "ASCII" # был заменен на £ . В других регионах, возможно, в ASCII не было скобок и т. Д.
  • 4
    Подобный набор символов ATASCII для 8-битных компьютеров Atari также не содержал {}, а также ~ и `.
Показать ещё 11 комментариев
135

Это c trigraph. ??! |, поэтому ??!??! - оператор ||

  • 5
    зачем кому-то пользоваться ??! вместо | ??? /
  • 3
    trigraph пришел из периода, когда у какой-то клавиатуры не было всех клавиш, которые они имеют сейчас. Это также помогает, когда некоторый текстовый редактор зарезервировал специальные символы для особых вещей. В основном это пережиток прошлого и способствующий викторине;)
Показать ещё 1 комментарий
52

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

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

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

(акцент мой)

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

  • 5
    ⁺¹ для таблицы других триграфов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню