Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 68
Текст из файла (страница 68)
суре со1огя = (гег), Ь1це, дгееп, уе11ои, огапде, иЬ)ге, Ь1асК)г со1огяес = аек ох со1огя; чак яеС1, яеС2 : со1огяегг Переменным множественного типа яег1 и яег2 можно следуюшим образом при;аоить постоянные значения: яег1: = (тес), Ь1це, уе11ои, ипдсе); яег2: = [Ь1аск, Ь1це) г Множественные типы в языках Мог)ц(а-2 и Моди!а-3 практически совпалают с соотзетствуюшнми типами в языке Рааса( за исключением небольших синтаксических изменений и некоторых дополнительных операций.
Константные множества заюцочаются в 253 5.9. Множества фиг)рные скооки [( ]). Скобкам может предшествовать имя типа этих констант. Рас- смотрим следующее объявление множественного типа данных: ТЕРЕ весуре1 = ВЕТ ОЕ [ген, Ь1ие, сгееп, уе11ои]; эесуре2 = ЯЕТ ОЕ [Ь1це, уе11он]; ЗГДЕ эегчаг1 : весуре1( В программе, содержащей эти обьявления, константа (Ь1це) может определяться неоднозначно.
Однако в операторе зесчаг1:= весуре1 (Ь1це); тип константы (Ь1це ) очевиден. В языке Рааса! существует одна форма записи этой константы, [ Ь1 се ] . что не позволяет указать ее тип. В языке Модо]а-2, подобно языку Рааса(, не указано минимально возможное количество элементов в множестве, так что зта величина также определяется в зависимости от реализации. В языках Рааса! и Моби[а-2 переменные множественных типов, как и переменные перечислимых типов, не могут ни вводиться, ни выводиться. Множества широко используются для упрощения и сокращения составных булевских выражений, содержащих оператор Ой. Например, оператор ке (сп = 'а') ог (сЛ = 'е') ог (сп = '1') ог (сп = 'о') ог (сЬ = 'ц ) можно заменить оператором 5.9.2.
Оценка Несмотря на то что язык А([а создавался на основе языка Рааса], множественные типы данных в языке Ада отсутствуют. Вместо этого разработчики языка А([а добавили оператор принадлежности переменной к множеству переменных перечислимого типа. Зто позволило выполнять одну из наиболее нужных операций над множествами. Отметим, что множества, в которых можно выполнять проверку принадлежности, очевидно, представляют собой просто перечислимые значения, являющиеся константами. В лругих языках.
не содержащих множественные типы данных, операции над множествами должны выполняться с массивами, причем команды, предусматривающие эти операции, должны создаваться пользователем. Зто не трулно, хотя, конечно, более громоздко. и. весьма вероятно, значительно менее эффективно. Например, если множество гласных букв в языке Рааса! представлено как массив спаг, то проверка наличия гласной буквы в данной символьной переменной будет требовать цикла, просматривающего массив с гласными. В то же время, если гласные буквы были представлены в виде множества. то этой же цели можно достичь одним применением оператора Еп.
Зто не только удобно лля программистов. но и способствует эффективному использованию компьютера. В обоих случаях гораздо удобнее обращаться с множеством как с единым целым, в то время как массив должен просматриваться поэлементно. Массивы, разумеется, намного гибче множеств; они допускают выполнение значительно большего количества операций, более сложные формы и большую свободу выбора типа элементов. Фактически, если массивы ограничить максимальной ллиной 32 [как это сделано лля множеств во многих реализациях языка Рааса!), пользователи не сочли бы их прием- Глава 5.
Типы данных .-.емыми. Множества предлагают альтернативный вариант, приносящий гибкость в жертву .=фелтивности и предназначенный дяя определенного класса приложений. 5.9.3. Реализация множественных тинов данных Множества, как правило, содержатся в памяти в виде строки битов. Например.
пусть чожество имеет в качестве базового следующий порядковый тип: ав ар~) Б этом случае переменные этого типа могут использовать первые 16 бит машинного . ова. причем бит ) будет представлять присутствующий элемент, а бит 0 — отс>тстз ющий. При использовании такой схемы значение с ажно представить в виде 010000100000010 Выигрыш от такого подхода заключается в возможности определить результат типичной зерации объединения множеств с помощью одной машинной команды — логического ..1И.
Если количество элементов базового множества не превышает размера машинного :лова, то операцию принадлежности к множеству также можно произвести с помощью зной команды. Например, для переменной множественного типа зегсйагз проверка -з принадлежность элемента к множеству выглядит следующим образом: дп зетсЛагз .:Ри этом процесс может выполняться с помощью операции логического И между двумя . зерандами, представленными в виле строк битов.
5.10. Указатели Указателем (ро(пгег) называется переменная, диапазон значений которой состоит из адресов ячеек памяти и специального значения — нулевого адреса. Значение нулевого ал:еса не является реальным адресом и используется только для обозначения того. что указа-ель в данный момент не может использоваться для обращения ни к какой ячейке памяти. Указатели разработаны лля применения в двух различных сферах. Во-первых. они по ~вогчют использовать некоторые выгоды косвенной адресации, широко применяемой в протраммировании на языках ассемблера. Во-вторых, указатели предлагают метод динамичсск ь -э управления памятью: их можно использовачь для доступа к области с динамическим р.ычещением памяти, обычно называемой кучей (Ьеар), или динамической памятью. Переменные, динамически размещаемые в куче, называются динамическими (йс ш')паш1с каvаЫез).
Часто они не содержат связанных с ними илентификаторов. и ссы.-.зться на них можно только с помощью указателей и ссылок (гебегепсез). Эти не имеющие имен переменные называются безымянными (апопушоцз чаг(аЫез). Именно в 1 оп чедавно появившейся области использования указателей н возникают важнейшие вонр:ы разработки.
Указатели, в отличие от массивов и записей, не относятся к структурным типам данных, хотя они и описываются с помощью оператора типа (оператора * в языках С и Г -. , ператора ессвев в языке Ада и оператора " в языке Разса!). Более того, онн отлич:ио и 5.) О. Укозатели 255 ся и от скалярных переменных, поскольку они чаше используются для обращения к лргим переменным, чем лля хранения каких-либо данных. Использование указателей в указанных случаях облегчает создание программ на языке.
Предположим, что нам нужно реализовать динамическую структуру наподобие двоичного дерева в языке со структурой, схожей со структурой языка ЕОКТКАХ 77, ие имеющего указателей. Такая задача потребует от программиста создания и поддержания пула доступных узлов дерева, что, вероятно, придется реализовывать в форме парылельных массивов. Кроме того, поскольку в языке ЕОКТКАХ 77 отсутствует линамическое управление памятью, от программиста потребуется приблизительная оценка максимального числа требуемых узлов. Очевидно, что такой способ работы с двоичными деревьями неуклюж и громоздок. 5.10.1. Вопросы разработки Основными вопросами разработки.
характерными лля указателей, являются следующие ° Каковы область видимости и время жизни переменных указателей? ° Каково время жизни динамических переменных". ° Ограничены ли указатели типом той величины, которую они могут адресовать". ° Используются ли указатели лля динамического управления памятью, лля косвенной адресации или для обеих целей? ° )Вглжен лц язык поддерживать указатели, ссылки или оба вила переменных? 5.10.2. Операции иад указателями Языки, в которых предусмотрен тип указателей, содержат, как правило, две основные операции над ними: присваиванне и разыменование. Первая из этих операций присваивает указателю некоторый алрес.
Если эти переменные используются только для управления динамической памятью, то лля их инициализации используется механизм размещения в памяти (реализуемый оператором или встроенной подпрограммой). Если же указатели используются лля обеспечения косвенной адресации переменных, не относящихся к динамическим, то лля выборки адреса переменной должен использоваться явный оператор или встроенная подпрограмма, после чего ланный адрес может присваиваться указателю. Появление в выражении переменной, являющейся указателем, можно интерпретировать двумя различными способами.
Во-первых, указатель можно рассматривать как ссылку на содержимое ячейки памяти, с которой связана переменная, т.е. в данном случае указатель — это адрес. Таким же образом можно интерпретировать входящую в выражение переменную, не являюгцуюся указателем, хотя в этом случае переменная может не быть адресом памяти. Впрочем. указатель также можно рассматривать как ссылку на значение той ячейки памяти, адрес которой находится в ячейке памяти, с которой связан данный указатель. В этом случае указатель интерпретируется как косвенная ссылка.
Первый из упомянутых случаев является обычной ссылкой с использованием указателя, тогда как во втором случае в выражение входит результат разыменования (дегеГегепс~пй) указателя. Разыменованис. принимающее ссылку через один уровень косвенной адресации, является второй основной операцией с указателями. Для того чтобы пояснить понятие разыменования, рассмотрим переменную-указатель рег, связанную с ячейкой памяти, имеющей значение 256 Глава 5. Типы данных : 80 Прелположим, что ячейка памяти с алресом 7080 содержит значение 206. Обычная .; ылха на переменную рг. г даст значение 7080, а разыменованная — 206. Разыменование может быть явным и неявным.