Назначение последовательностей Триграфов в C++?

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

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

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

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

мой вопрос в том, какова цель использования триграфов? есть ли практическое преимущество использования триграфов?

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

UPD2: в Visual Studio 2010 по умолчанию отключена поддержка trigraph.

9 ответов


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

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

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

'\?'

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

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

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

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

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

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

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


дополнение:

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


С The C++ Programming Language специальное издание, стр. 829

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

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


дети! :-)

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

посмотрите рядом с "P" ключ: http://www.9999hp.net/keyboard/temp/1389260-big.jpg

Хммм. Трудно сказать. Рядом с "возвращением каретки" есть дополнительная кнопка, и я мог бы вернуть ее назад: возможно, это была пара " [ " / " ]", которая отсутствовала. Во всяком случае, эта клавиатура вызовет у вас горе, если вам придется написать 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

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

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


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

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


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


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

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

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