Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 60
Текст из файла (страница 60)
что в строках языков С и С++ вместо хранения длины строки используется спешильный символ лля указания конца символьной строки. Третьей возможностью является разрешение строк с переменной неограниченной длиной. как это сделано в языках ЯКОВОВ и Рег1. Такие строки называются строками с динамической длиной (бупаш(с 1епйгп згппб). Подобное проектное решение требует расходов на динамическое размещение строк в памяти и удаление их из памяти, но обеспечивает максимальную гибкость.
5.3.4. Оценка Строковые типы значительно влияют на легкость написания программ. Обрашение со строками как с массивами может быть более громоздким, чем обрашение с элементарным строковым типом. Использование символьных строк в качестве элементарного типа не усложняет ни сам язык, ни его компилятор, поэтому трудно объяснить их отсутствие в некоторых современных языках программирования. Разумеется. отсутствие таких типов может компенсироваться наличием стандартных библиотек подпрограмм для работы со строками. Операшги со строками. например простое сопоставление с образцом и конкатенация, необхолимы и должны сушестаовать для величин, принадлежащих к строковым типам.
Очевидно также. что хотя строки с линамической длиной и более гибкие, но эта дополнительная гибкость должна сопоставляться с затратами на их реализацию. 5.3.5. Реализация символьных строк Символьные строки иногда поддерживаются с помошью аппаратного обеспечения, но в большинстве случаев лля хранения строк в памяти, поиска в строке и обработки строк все же использ) ется программное обеспечение. Если символьные строки представляются в виле массивов символов, то язык часто довольствуется небольшим числом операций. Дескриптор статического строкового типа (елинственное, что требуется во время компиляции) содержит три поля.
Для статических символьных строк второе поле содеркит длину типа (в символах). Третье поле является адресом первого символа. Такой дескриптор изображен на рис. 5.2. Как показано на рис. 5.3, строки с ограниченной динамической длиной требуют наличия динамического дескриптора, содержашего текушую и максимально возможную длины строки. Строкам с динамической длиной нужен более простой динамический лескриптор. поскольку он должен солержать только текущую длин) строки.
Строки с ограниченной динамической длиной в языках С и С++ не требуют наличия динамических дескрипторов. поскольку конец строки помечен символом нуля. Им не н) жна максимальная длина. поскольку в этих языках значения индексов при обрашении к массив) не проверяются на предмет выхода за пределы интервала. 222 Глава 5.
Типы данных Строки со статической и ограниченной динамической длиной не требуют особого динамического распределения памяти. Для строк с ограниченной динамической длиной память, достаточная лля содержания строки максимальной длины, выделяется при связывании переменной с памятью, таким образом, выполняется только один процесс размещения в памяти.
Максимальная длина строки фиксируется во время компиляции. Рис. 5З. Динамический деск- риптор строк с ограниченной динаиической длиной Рис. 5.2. Статический де- скри~тор строк со стати- ческой длиной Строки с динамической длиной требуют более сложного управления памятью. Длина строки (а следовательно и память, с которой она связывается) должна расти и уменьшаться динамически. Существует два возможных подхода к решению проблемы динамического распределения памяти.
Во-первых, строки могут храниться в связных списках, таким образом, при росте строки новые ячейки будут выделяться где-либо в динамической памяти. Недостатком этого метода является большое количество памяти, занимаемое связями при представлении строк в виде списков. Альтернативным вариантом является хранение полных строк в смежных ячейках памяти.
Осложнения появляются при росте строк; как может ячейка памяти, соседствующая с уже существующей ячейкой, содержать строковую переменную? Довольно часто такие ячейки недоступны. Вместо этого производится поиск новой области памяти, способной вместить новую строку, при этом старая часть строки перемешается в эту область памяти, после чего ячейки памяти, содержавшие старую строку, освобождаются. Несмотря на то что использование метода связных списков требует большего объема памяти, происходящие при этом процессы размещения в памяти и удаления из нее просты. Впрочем, некоторые операции со строками замедляет отслеживание указателей. С другой стороны, хранение полных строк в смежных ячейках памяти приводит к ускорению выполнения операций над строками и требует значительно меньшего объема памяти.
Несмотря на это, процесс размещения в памяти выполняется медленнее. Метод смежных ячеек памяти порождает общую проблему управления распределением и освобождением ячеек памяти переменного размера. Подробнее этв проблема рассматривается в разделе 5.!ОЛ0.3. 223 5.3. Символьные строки 5.4. Порядковые типы, определяемые пользователем Порядковым (огб!па)) называется тип, в котором область возможных значений переменных может быть легко связана с последовательностью натуральных чисел. В языках Рааса) и Ада, например, основными порялковыми типами являются целый, символьный и булевский типы. Во лгногих языках пользователи сами могут определять две разновидности порядковых типов: перечислимые типы и ограниченные типы.
$.4.1. Перечиспиддые типы Перечислимым (епшпегайоп) называется тип, в описании которого перечислены все возможные значения, являюшиеся символьнылги константами (в языке Ада они также могут быть символьными литералами). Обычный перечислнмый тип показан в следующем примере из языка Ада: Ку)ре ВКАТЯ дв (Моп, Тие, Хес), ТЬо, Рг1, Яас, Яцп); Основным вопросом разработки, характерным для перечислимых типов, является слелуюший: может ли литеральная константа появляться в нескольких описаниях типа, и если да, то как проверяется в программе тип конкретного литерала? 5.4.
1. 1. Структуры В языке Рааса) литеральную константу в ланной среде ссылок нельзя использовать в нескольких описаниях перечислимого типа. Переменные, принадлежашие к перечислимым типам. могут использоваться в качестве индексов массивов, переменных цикла ког, выражений оператора ветвления савв, но не могут ввалиться или выводиться. Два перечислимых типа переменных и/или литералов, принадлежащих к одному типу, могут сравниваться с помощью операторов отношений, при этом результат сравнения определяется их относительными положениями в объявлении. Например, во фрагменте программы куре со1оггуре = (гес), Ь1ие, дгееп, уе11он) г чег со1ог: со1огсуре; со1ог: = Ь1це; Дг со1ог > гег) булевское выражение в операторе дг' будет вычислено как истинное.
В языках АМЯ! С и С++, как и в языке Рааса!, одна литеральная константа не может появляться в нескольких описаниях перечислимого типа в данной среде ссылок. Перечислимые величины языков АХЯ1С и С + неявно преобразуются в целые, так что они подчиняются только правилам использования целых чисел. Перечислимые типы языка Ада подобны соответствуюшим типам языка Разса1, за исключением того, что литералы могут появляться в нескольких объявлениях в одной и той же среде ссылок. Такие литералы называются перегруженнымн литералами (очег1оадег) 1!гега!з).
Правило разрешения перегрузки (т.е. определения типа данного экземпляра литерала) состоит в том, что тип должен определяться контекстом, в котором появляется литерал. Например, если сравниваются перегруженный литерал и переменная перечислимого типа, то тип литерала считается совпадаюшим с типом переменной. 224 Глава 5. Типы данных В некоторых случаях при появлении перегруженного литерала программист должен указать спецификации типа.
Прелположим. что в программе есть лва следующих перечислимых типа: суре ЧОЬ)ЕЕ5 хв ( А', 'Е', '1', 'О', 'Е'); Предположим далее, что в программе использован ш)кл Еок. переменные которого сле- дующим образом принимают значения типа уОне15: Гок ЬЕТТЕА хп 'А'..'О' 1оор Проблема заключается в том. что компилятор не может корректно определить тип переменной АНЕТТЕ)(, поскольку дискретный диапазон (в данном случае 'А' .. ' О') определен неоднозначно. (В языке Аг(а тип переменной цикла Еок неявно опрелеляется компилятором.
Она получает тип дискретного диапазона. задаюшегося в операторе.) Решением проблемы является следующее использование спецификатора типа для литералов дискретного диапазона: кок ЬЕТТЕВ Еп ЧОХЕЬ5'('А')..ЧОЫЕ15'('О') Хоор Переменные перечислимых типов могут выводиться. а перечислимые литералы мог) т вводиться при наличии пакета техт 1О языка Ада. Эти операции требуют настраиваемых реализаций встроенных пакетов для специфических перечислимых типов.