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


128

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

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

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

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

У меня вопрос, зачем использовать триграфы? Есть ли практическая польза от использования триграфов?

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

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


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

2
Может случиться так, что некоторые терминалы и / или виртуализация не позволяют легко получить доступ к некоторым персонажам. По моему опыту, главный нарушитель - тильда.
Francesco

1
набирая это на моей DE-клавиатуре с мертвыми клавишами, # - это клавиша рядом с возвратом, \ - это "AltGr" + "ß" (рядом с 0), ^ - это "^" + "^" (из-за мертвых клавиш; рядом с 1) , [равно «AltGr» + «8»,] равно «AltGr» + «9», | равно "AltGr" + "<", {равно "AltGr" + "7",} равно "AltGr" + "0", а ~ равно "~" + "~" (из-за мертвых клавиш, чуть выше #). так что ничего страшного. мои пальцы как будто сами набирают эти комбинации :-D
nonchip

1
Я подумал, что нормально иметь две раскладки клавиатуры и переключать их в соответствии с работой, которую я выполняю на компьютере. Это обычный способ в Центральной Европе. Использовать эти триграфы довольно жутко. Я бы проголосовал за удаление этого из стандарта.
VX

Ответы:


98

Этот вопрос (о близких орграфах) есть ответ.

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

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

'\?'

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

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

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

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

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

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

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


Приложение:

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


Совместимость с C - единственная причина? Возможно ли их встретить в современных программах на C ++?
Кирилл В. Лядвинский 05

Да, C ++ также поддерживает триграфы и орграфы.
Майкл Берр,

4
Насколько я помню, по крайней мере для одного компилятора, который я использовал (g ++?), Требуется явная опция командной строки перед преобразованием триграфа и / или орграфа, в противном случае выдается предупреждение, но без замены.
KTC

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

1
Это действительно действует мне только на нервы, когда триграфы расширяются в комментариях, чтобы делать удивительные вещи.
Джошуа

23

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

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

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

клавиатура

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

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

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


1
На клавиатуре есть кнопка сброса. Это потрясающе! Странно, что это сразу привлекло мое внимание.
l46kok

11
Тот, кто хочет использовать C ++ 17 на машине EBCDIC, должен быть заключен в тюрьму за некрофилию.
SF.

Если платформа не имеет символов на всех , кроме тех , в ISO646, может не все , что может быть сделано с триграфами быть сделано, требуя , чтобы каждая реализация определяет либо обратную косую черту или еще какой - либо символ , который не в наборе C символов в виде «мета», заменить все ссылки на обратную косую черту в стандарте на «мета» и добавить обратную косую черту / мета-экранирование для любых элементов набора символов C, которых нет в ISO-646?
supercat

22

Из The C++ Programming LanguageSpecial Edition, стр. 829

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

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


8
«Внедрение нового оборудования может быть удручающе медленным процессом». Особенно по сравнению с быстрым и безболезненным процессом стандартизации функций языка программирования.
jforberg 04

4
Если это кладж для раскладок клавиатуры, то забавно, что нет триграфа, например, для набора текста `, который отсутствует в итальянской и некоторых других раскладках клавиатуры
badp

15

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


2
Значит ли это, что я никогда не буду использовать их в реальной жизни?
Кирилл В. Лядвинский 05

1
В какой стране ты живешь? Не на всех клавиатурах для всех языков есть необходимые клавиши.
Дэвид Торнли

2
Да, но вам может потребоваться знать о его существовании в случае, если один из них вызовет неожиданный результат, например, в строковом литерале.
CB Bailey,

4
@ Дэвид Торнли: Большинство современных систем поддерживают все основные символы C ++, даже если они не находятся в обычном месте или требуют для ввода последовательности модификаторов. Триграфы необходимо было поддерживать в исходном коде только в тех системах, где символ фактически не может быть представлен в системном наборе символов. Я все еще утверждаю, что такие системы чрезвычайно редки.
CB Bailey,

9

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


Да этот «иностранный язык»! :-)
Roboprog 05

На самом деле они мало что говорят, кроме «результатов внутреннего исследования отзывов клиентов», но ну ладно. Я удивлен, что EBCDIC все еще широко используется (и что эти системы предполагают использовать компиляторы C ++ 0x)
peterchen

5

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

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

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


PL / 1 = версия C IBM (более или менее). См. Мой комментарий: Терминалы IBM не имеют ключей '{' / '}' :-( В противном случае
довольно

3

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


1
Я всегда подозревал, что IBM не говорит по-английски :-)
Roboprog

3

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

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


4
Триграфы на самом деле не относятся к вводу данных (они делают код нечитаемым), они больше относятся к системам, которые на самом деле не имеют необходимых символов. Если система может записывать и отображать символ - даже если необходимо ввести последовательность клавиш, подобную триграфу, - было бы гораздо проще не сохранять последовательность триграфа в источнике.
CB Bailey,

2

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.