Вопрос

Согласно стандарту C++'03 2.3/1:

Прежде чем произойдет какая-либо другая обработка, каждое появление одной из следующих последовательностей из трех символов («триграфические последовательности») заменяется одним символом, указанным в таблице 1.

----------------------------------------------------------------------------
| trigraph | replacement | trigraph | replacement | trigraph | replacement |
----------------------------------------------------------------------------
| ??=      | #           | ??(      | [           | ??<      | {           |
| ??/      | \           | ??)      | ]           | ??>      | }           |
| ??’      | ˆ           | ??!      | |           | ??-      | ˜           |
----------------------------------------------------------------------------

В реальной жизни это означает, что код printf( "What??!\n" ); приведет к печати What| потому что ??! представляет собой триграфическую последовательность, заменяемую на | характер.

Мой вопрос: какова цель использования триграфов? Есть ли практическая польза от использования триграфов?

УПД:В ответах упоминалось, что на некоторых европейских клавиатурах нет всех знаков препинания, поэтому программистам, не проживающим в США, приходится использовать триграфы в повседневной жизни?

УПД2:В Visual Studio 2010 поддержка триграфов по умолчанию отключена.

Это было полезно?

Решение

Этот вопрос (о тесно связанных орграфах) есть ответ.

Это сводится к тому, что набор символов ISO 646 не содержит всех символов синтаксиса C, поэтому существуют некоторые системы с клавиатурами и дисплеями, которые не могут обрабатывать символы (хотя я полагаю, что это довольно редкие случаи). настоящее время).

В общем, использовать их не обязательно, но о них нужно знать именно для той проблемы, с которой вы столкнулись.Триграфы являются причиной того, что?'символ имеет escape-последовательность:

'\?'

Итак, несколько способов избежать проблемы с вашим примером:

 printf( "What?\?!\n" ); 

 printf( "What?" "?!\n" ); 

Но вы должны помнить, когда вы печатаете их? ' Персонажи, которых вы можете начать триграф (и это, конечно, никогда не то, о чем я думаю).

На практике триграфы и диграфы — это то, о чем я вообще не беспокоюсь изо дня в день.Но вы должны знать о них, потому что раз в пару лет вы сталкиваетесь с связанной с ними ошибкой (и остаток дня вы проклинаете их существование).Было бы неплохо, если бы компиляторы можно было настроить на предупреждение (или ошибку) при обнаружении триграфа или орграфа, чтобы я мог знать, что у меня есть что-то, с чем мне следует сознательно разобраться.

И просто для полноты: орграфы гораздо менее опасны, поскольку они обрабатываются как токены, поэтому орграф внутри строкового литерала не будет интерпретироваться как орграф.

Чтобы получить хорошее представление о различных развлечениях с пунктуацией в программах на C/C++ (включая ошибку триграфа, которая наверняка заставила бы меня рвать на себе волосы), взгляните на Статья Херба Саттера GOTW #86.


Приложение:

Похоже, что GCC не будет обрабатывать (и предупреждать) триграфы по умолчанию.Некоторые другие компиляторы имеют возможность отключить поддержку триграфа (например, IBM).Microsoft начала поддерживать предупреждение (C4837) в VS2008, которое необходимо явно включить (с помощью -Wall или чего-то еще).

Другие советы

Специальное издание Язык программирования C ++ , стр. 829

  

Специальные символы ASCII [, ] , {, } , | и \ занимают позиции набора символов, обозначенные ISO как буквенные. В большинстве европейских национальных наборов символов ISO-646 эти позиции занимают буквы, которых нет в английском алфавите.

     

Предоставляется набор триграфов, позволяющих выражать национальные символы переносимым способом с использованием действительно стандартного минимального набора символов. Это может быть полезно для обмена программами, но это не облегчает людям чтение программ. Естественно, долгосрочное решение этой проблемы для программистов C ++, чтобы получить оборудование, которое хорошо поддерживает и их родной язык и C ++. К сожалению, это кажется невозможным для некоторых, и внедрение нового оборудования может быть крайне медленным процессом.

Дети сегодня!:-)

Да, зарубежное оборудование, например терминал IBM 3270.Насколько я помню, у 3270 нет фигурных скобок!Если вы хотите написать C на мини-/мейнфрейме IBM, вам должен был используйте жалкие триграфы для каждой границы блока.К счастью, мне нужно было всего лишь написать программу на языке C, чтобы подражать некоторые миникомпьютеры IBM, на самом деле не пишут программное обеспечение C на Система/36.

Посмотрите рядом с клавишей «P»:

keyboard

Хм.Трудно сказать.Рядом с «возвратом каретки» есть дополнительная кнопка, и я мог бы расположить ее задом наперед:возможно, отсутствовала пара «[» / «]».В любом случае, эта клавиатура вызвала бы у вас огорчение, если бы вам пришлось писать на C.

Кроме того, эти терминалы отображают EBCDIC, «родной» набор символов мейнфреймов IBM, а не ASCII (спасибо Павлу Минаеву за напоминание).

С другой стороны, как сказано в руководстве GNU C:"Тебе не нужны повреждения мозга." Компилятор gcc оставляет эту "функцию" отключенной по умолчанию.

Они предназначены для использования в системах, в которых отсутствуют некоторые символы из базового набора символов C ++. Излишне говорить, что такие системы чрезвычайно редки.

Триграфы были предложены для удаления в C ++ 0x. Тем не менее, кажется, все еще есть веские аргументы в их поддержку - см. Документ комитета C ++ N2910 , где это обсуждается. Судя по всему, EBCDIC является одним из основных опорных пунктов, где они необходимы.

Я видел триграфы, использовавшиеся в начале 90-х для помощи в преобразовании программ PL / 1 из мэйнфрейма для запуска / компиляции / отладки на ПК.

Они занимались редактированием PL / I на ПК с использованием компилятора PL / I to C, и они хотели, чтобы код работал, когда он вернулся на мэйнфрейм, который не поддерживал фигурные скобки. Я предположил, что они могут использовать макросы, такие как

#def BEGIN {    
#def END }  

или как более дружественная альтернатива PL / I

#def BEGIN ??<
#def END ??>

и если они действительно хотят стать модными, они могут попробовать

#ifdef MAINFRAME
    #def BEGIN ??<
    #def END ??>
#else
    #def BEGIN {    
    #def END }  
#endif

и тогда программа будет выглядеть так, как будто она написана на Паскале. Они просто смешно смотрели на меня и не разговаривали со мной до конца дня. Я не думаю, что я их виню. :)

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

Некоторые европейские клавиатуры не имеют (не?) всех знаков препинания, которые были на американских клавиатурах, потому что они нуждались в клавишах для своих необычных буквенных символов. Так, например, (придумывая это), на шведской клавиатуре должно быть кольцо A, где была фигурная скобка.

Для удобства этих пользователей триграфы - это способ ввода знаков препинания с использованием только самых распространенных символов ASCII.

В первую очередь потому, что стандарт C ввел их еще в 1989 году, когда были проблемы с наличием символов, которые отображают триграфы на некоторых машинах. Ко времени публикации стандарта C ++ в 1998 году потребность в триграфах была невелика. Они бородавка на С; они такие же бородавки на C ++. В них была необходимость, особенно за пределами англоязычного мира, поэтому они были добавлены в Си.

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

Если вы не знаете, для чего они, вы не должны их использовать.

Тем не менее, полезно знать о них, поскольку вы можете случайно и непреднамеренно использовать их в своем коде.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top