Подтвердить что ты не робот

Назначение последовательностей Trigraph в С++?

Согласно С++ '03 Standard 2.3/1:

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

'\?'

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

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

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

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

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

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

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


Приложение:

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

Ответ 2

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

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

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

Ответ 3

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

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

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

keyboard

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

#def BEGIN {    
#def END }  

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

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

и если они действительно хотели получить фантазию, они могли попробовать

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

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

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

Ответ 7

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

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

Ответ 8

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

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

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

Ответ 9

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