Назначение последовательностей триграфа в C ++? - PullRequest
118 голосов
/ 05 августа 2009

В соответствии со стандартом C ++ '03 2.3 / 1:

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

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

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

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

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

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

Ответы [ 9 ]

89 голосов
/ 05 августа 2009

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

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

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

'\?'

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

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

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

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

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

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

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


Добавление:

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

20 голосов
/ 05 августа 2009

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

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

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

18 голосов
/ 05 августа 2009

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

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

Посмотрите рядом с клавишей "P": http://www.9999hp.net/keyboard/temp/1389260-big.jpg

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

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

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

13 голосов
/ 05 августа 2009

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

8 голосов
/ 05 августа 2009

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

4 голосов
/ 05 августа 2009

Я видел триграфы, использовавшиеся в начале 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

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

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

3 голосов
/ 05 августа 2009

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

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

2 голосов
/ 05 августа 2009

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

2 голосов
/ 05 августа 2009

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

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

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

...