В программировании на компьютере диграфы и триграфы — это последовательности из двух и трех символов соответственно, которые появляются в исходном коде и, согласно спецификации языка программирования , должны рассматриваться как отдельные символы. Триграфы были удалены из языка C++ и будут удалены из C с C23 , поэтому, скорее всего, уже не используются на практике ни в C, ни в каком-либо другом распространенном языке (использование их в языке J является исключением). В современном мире Unicode / UTF-8 (даже просто с ASCII ) нет необходимости в триграфах при проектировании языка, которые считались обузой, и ни в настоящих диграфах, которые, вероятно, имеют очень мало пользователей, по крайней мере, в этих языках.
Существуют различные причины использования диграфов и триграфов: клавиатуры могут не иметь клавиш для покрытия всего набора символов языка, ввод специальных символов может быть затруднен, текстовые редакторы могут резервировать некоторые символы для специального использования и т. д. Триграфы также могут использоваться для некоторых кодовых страниц EBCDIC , в которых отсутствуют символы, такие как и .{
}
Базовый набор символов языка программирования C — это подмножество набора символов ASCII , включающее девять символов, которые лежат за пределами инвариантного набора символов ISO 646. Это может создать проблему для написания исходного кода , когда используемая кодировка (и, возможно, клавиатура ) не поддерживает ни один из этих девяти символов. Комитет ANSI C изобрел триграфы как способ ввода исходного кода с помощью клавиатур, которые поддерживают любую версию набора символов ISO 646. [1]
Триграфы обычно не встречаются вне тестовых наборов компилятора . [2] Некоторые компиляторы поддерживают опцию отключения распознавания триграфов или отключения триграфов по умолчанию и требуют опции для их включения. Некоторые могут выдавать предупреждения, когда они сталкиваются с триграфами в исходных файлах. Borland предоставила отдельную программу, препроцессор триграфов ( ), которая должна использоваться только тогда, когда требуется обработка триграфов (обоснованием было максимизировать скорость компиляции).TRIGRAPH.EXE
Разные системы определяют разные наборы диграфов и триграфов, как описано ниже.
Ранние версии ALGOL предшествовали стандартизированным наборам символов ASCII и EBCDIC и обычно реализовывались с использованием шестибитного кода символа , специфичного для производителя . Ряд операций ALGOL либо не имели кодовых точек в доступном наборе символов, либо не поддерживались периферийными устройствами, что приводило к ряду замен, включая :=
for ←
(присваивание) и >=
for ≥
(больше или равно).
Язык программирования Pascal поддерживает диграфы (.
, .)
, (*
и *)
для [
, ]
, {
и }
соответственно. В отличие от всех других случаев, упомянутых здесь, (*
и *)
были и все еще широко используются. Однако многие компиляторы рассматривают их как другой тип блока комментариев, а не как настоящие диграфы, то есть комментарий, начатый с , (*
не может быть закрыт с помощью }
и наоборот.
Язык программирования J является потомком APL , но использует набор символов ASCII, а не символы APL . Поскольку диапазон печати ASCII меньше, чем специализированный набор символов APL, символы .
(точка) и :
(двоеточие) используются для склонения символов ASCII, эффективно интерпретируя униграфы, диграфы или редко триграфы как отдельные «символы». [3]
В отличие от использования диграфов и триграфов в C и C++ , в J нет их односимвольных эквивалентов.
Препроцессор C (используемый для C и с небольшими отличиями в C++ ; см. ниже) заменяет все вхождения девяти последовательностей триграфов в этой таблице их односимвольными эквивалентами перед любой другой обработкой (до C23 [4] ). [5] [6]
Программист может захотеть разместить два вопросительных знака вместе, но не заставлять компилятор обрабатывать их как введение триграфа. Грамматика C не допускает двух последовательных ?
токенов, поэтому единственные места в файле C, где можно использовать два вопросительных знака подряд, — это многосимвольные константы, строковые литералы и комментарии. Это особенно проблема для классической Mac OS , где константа '????'
может использоваться как тип файла или создатель. [7] Чтобы безопасно разместить два последовательных вопросительных знака внутри строкового литерала, программист может использовать конкатенацию строк "...?""?..."
или escape-последовательность "...?\?..."
.
???
сама по себе не является последовательностью триграфов, но если за ней следует такой символ, -
то она будет интерпретироваться как ?
+ ??-
, как в примере ниже, в котором ?
перед /
. стоит 16 с.
Триграф ??/
может использоваться для ввода экранированного символа новой строки для склеивания строк; это необходимо учитывать для правильной и эффективной обработки триграфов в препроцессоре. Это также может вызывать сюрпризы, особенно в комментариях. Например:
// Будет ли выполнена следующая строка????????????????/ a ++ ;
которая представляет собой одну логическую строку комментария (используется в C++ и C99 ), и
/??/ * Комментарий * ?? / /
что является правильно сформированным блочным комментарием. Эту концепцию можно использовать для проверки триграфов, как в следующем примере C99, где будет выполнен только один оператор return.
int trigraphsavailable () // возвращает 0 или 1; стандарт языка C99 или более поздний { // доступны ли триграфы??/ return 0 ; return 1 ; }
В 1994 году нормативная поправка к стандарту языка Си, C95 , [8] [9], включенная в C99, предоставила диграфы в качестве более читаемых альтернатив пяти триграфам.
В отличие от триграфов, диграфы обрабатываются во время токенизации , и любой диграф всегда должен представлять собой полный токен сам по себе или составлять токен, %:%:
заменяющий конкатенационный токен препроцессора ##
. Если последовательность диграфов встречается внутри другого токена, например, строки в кавычках или символьной константы, она не будет заменена.
C++ (до C++14 , см. ниже) ведет себя как C, включая дополнения C99, но с дополнительными токенами, перечисленными в таблице. [10]
Обратите внимание, %:%:
что рассматривается как один токен, а не как два вхождения %:
.
В последовательности, <::
если последующий символ не является ни :
ни >
, то он <
рассматривается как токен предварительной обработки сам по себе, а не как первый символ альтернативного токена <:
. Это делается для того, чтобы определенные использования шаблонов не нарушались заменой.
Стандарт C++ делает следующий комментарий относительно термина «диграф»: [11]
Термин «диграф» (токен, состоящий из двух символов) не является идеально описательным, поскольку один из альтернативных токенов предварительной обработки — это
%:%:
и, конечно, несколько основных токенов содержат два символа. Тем не менее, те альтернативные токены, которые не являются лексическими ключевыми словами, в разговорной речи называются «диграфами».
Триграфы были предложены для удаления в C++0x , который был выпущен как C++11 . [12] Это вызвало противодействие со стороны IBM , выступавшей от своего имени и от имени других пользователей C++, [13] и в результате триграфы были сохранены в C++11. Затем триграфы были снова предложены для удаления (не только для удаления) в C++17 . [14] Это прошло голосование комитета, и триграфы (но не дополнительные токены) были удалены из C++17, несмотря на противодействие со стороны IBM. [15] Существующий код, который использует триграфы, может поддерживаться путем перевода из исходных файлов (анализа триграфов) в базовый исходный набор символов, который не включает триграфы. [14]
Калькуляторы Hewlett-Packard , поддерживающие язык RPL и метод ввода, обеспечивают поддержку большого количества триграфов (также называемых кодами TIO ) для надежной транскрипции несемибитных символов ASCII расширенного набора символов калькуляторов [16] [17] [18] на иностранных платформах и для облегчения ввода с клавиатуры без использования приложения CHARS . [19] [20] [17] [18] Первый символ всех кодов TIO — это a \
, за которым следуют два других символа ASCII, отдаленно напоминающих глиф, который нужно заменить. [19] [20] [17] [18] [21] Все остальные символы можно вводить с помощью специального \nnn
синтаксиса кода TIO, где nnn — это трехзначное десятичное число (с ведущими нулями , если необходимо) соответствующей кодовой точки (тем самым формально представляя тетраграф ). [19] [17] [18]
Текстовый редактор Vim поддерживает диграфы для фактического ввода текстовых символов в соответствии с RFC 1345. Ввод диграфов по умолчанию привязан к Ctrl+ . [22] Список всех возможных диграфов в Vim можно отобразить, введя .K:dig
GNU Screen имеет команду диграфа, привязанную к ++ по умолчанию . [23]CtrlA CtrlV
Lotus 1-2-3 для DOS использует + в качестве клавиши ввода , что позволяет упростить ввод многих специальных символов международного набора символов Lotus (LICS) [24] и набора многобайтовых символов Lotus (LMBCS).AltF1