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


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

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

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

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

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

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

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

9 114

9 ответов:

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

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

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

'\?'

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

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

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

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

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

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

для хорошего образования по различным забавам с пунктуацией в программах C / C++ (включая ошибку trigraph, которая определенно заставит меня вытащить волосы), взгляните на Herb Sutter's GOTW #86 article.


дополнение:

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

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

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

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

дети! : -)

да, иностранное оборудование, такое как терминал IBM 3270. У 3270, если я помню, нет фигурных скобок! Если вы хотите написать C на IBM mini / mainframe, вы пришлось используйте жалкие триграфы для каждой границы блока. К счастью, мне нужно было только написать программу на C, чтобы повторить некоторые МИНИКОМПЬЮТЕРНЫЕ средства IBM, на самом деле не пишут программное обеспечение C on система/36.

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

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

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

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

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

триграфы были предложены для удаления в C++0x. тем не менее, все еще есть сильный аргумент в их поддержку - см. c++ committee paper 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++. Была потребность в них-особенно за пределами англоязычного мира - вот почему они были добавлены к C.

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

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

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