CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2002 ГОД

Мысли о Паскале

Владислав Демьянишин nitromanit@mail.ru

(Продолжение, начало см. МК № 46, 51—52, 4, 6—7 (165, 170—171, 175, 177—178))

Совместимость типов

В чистом виде эквивалентность (равенство) типов переменных или значений параметров требуется только в случае передачи параметров при вызове процедур или функций (таким образом, типы фактических, т. е. передаваемых, и формальных, т. е. требуемых, параметров должны быть эквиваленты). В других Pascal-конструкциях используются несколько ослабленные (но более детальные) ограничения, называемые СОВМЕСТИМОСТЬЮ типов.

Выполнение операций в выражениях, а также операции сравнения переменных требуют, чтобы операнды имели совместимые типы. Совместимость типов двух переменных (или некоторых значений) имеет место, если выполняется хотя бы одно из следующих условий:

• Два типа эквивалентны (равны);

• Оба типа целые, либо вещественные;

• Один тип является ограниченным типом, причем его базовым типом является другой тип:

т. е. тип T2 может иметь значения в диапазоне 1..100, и любое значение этого типа попадает в диапазон допустимых значений для типа Shortint (-128..127), стало быть, типы T1 и T2 совместимы, т.е. могут взаимно заменяться в выражениях и сравнениях;

• Оба типа являются ограниченными, причем их базовым типом является один и тот же тип:

опять таки, типы T1 и T2, судя по диапазонам описанных для них значений, являются целыми — значит, эти типы совместимы;

• Оба типа являются множественными типами (см. главу «Множественные типы»), причем их базовые типы совместимы:

здесь конструкция немного сложнее, но принцип тот же; множественный тип T2 может содержать значения в диапазоне 1..10, то же касается и типа Byte, т. е. типы T1 и T2 совместимы;

• Оба типа являются упакованными символьными массивами (см. главу «Составные типы. Регулярные типы (массивы)») с одинаковым числом элементов;

• Один тип является строковым (см. главу «Строковые типы»), а другой либо также является строковым типом, либо упакованным символьным массивом, либо символьным типом;

• Один тип является ссылочным, а другой либо тоже ссылочный, либо является бестиповым указателем (см. главу «Ссылочные типы. Динамические переменные»);

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

Здесь я забежал немного вперед. Сейчас не стоит глубоко задумываться над последними пятью пунктами.

Есть специальное понятие —совместимость по присваиванию. Оператор присваивания считается корректным, если тип переменной в левой части совместим по присваиванию с типом выражения из правой части.

Проще говоря, переменной одного типа (той что слева) можно присвоить значение переменной (или результата выражения) другого типа (той что справа), если типы этих переменных совместимы по присваиванию.

Два типа являются совместимыми по присваиванию, если выполняется хотя бы одно из следующих условий:

• Оба типа эквивалентны и ни один из них не является файловым типом (см. главу «Файловые типы и ввод-вывод») или не является структурным типом, содержащим поле с файловым типом на одном из своих уровней;

• Оба типа являются совместимыми дискретными (целыми), и значения типа правой части попадают в диапазон возможных значений типа левой части (чтобы левая часть могла принять новое значение без возникновения ошибки от переполнения);

• Оба типа являются вещественными типами, и значения типа правой части попадают в диапазон значений типа левой части;

• Тип левой части является вещественным типом, а тип правой части является целым типом;

• Тип левой части является строковым типом, а тип правой части — либо строковым типом, либо символьным типом, либо упакованным символьным массивом;

• Оба типа являются совместимыми упакованными символьными массивами;

• Оба типа являются совместимыми множественными типами, причем множество из правой части целиком входит во множество из левой части;

• Оба типа являются совместимыми ссылочными типами, либо совместимыми процедурными типами;

• Тип левой части является процедурным типом, а правая часть представляет собой идентификатор процедуры или функции, причем с тем же числом параметров, что и у типа левой части; типы параметров должны быть эквивалентны, также эквивалентны типы возвращаемого результата (в случае функции);

• Оба типа объектовые, причем тип правой части является потомком типа левой части (см. главу «Средства объектно-ориентированного программирования»), либо оба типа являются ссылочными на совместимые объектовые типы.

Если в операторе присваивания не выполняется ни одно из этих условий, то на этапе компиляции или при выполнении программы выдается сообщение об ошибке.

Составные типы

Простые типы, о которых я рассказывал ранее, определяют различные множества атомарных (неразделимых) значений. Например, имеем переменную типа Longint, в которой все 4 байта (занимаемые ею в памяти) составляют какое-то единое числовое значение. Составные, или структурные типы, в отличие от простых, задают множества «сложных» значений; каждое значение из такого множества образует некоторый агрегат (совокупность) нескольких значений другого типа (или других типов). Можно сказать, что составные типы определяют некоторый способ образования новых типов из уже имеющихся, причем отдельные элементы составных значений могут иметь любой, в том числе составной, тип. Таким образом, Pascal допускает образование структур данных произвольной сложности, позволяя тем самым достичь адекватного представления в программе тех данных, с которыми она оперирует.

В Pascal’е определены следующие составные типы:

• Регулярные типы (массивы);

• Комбинированные типы (записи);

• Множественные типы;

• Строковые типы;

• Файловые типы;

• Объектовые типы.

Регулярные типы (массивы)

Регулярный тип, или попросту массив — это последовательность определенного количества элементов одного типа. Такая последовательность является одним целым — группой и именуется одним именем, а доступ к каждому элементу массива осуществляется через указание индекса (некое подобие порядкового номера) этого элемента сразу за именем массива, что очень удобно при программировании.

Для корректного описания массива необходимо задать такие характеристики:

• Общий тип для элементов массива, которым может быть любой базовый тип или произвольный тип, созданный самим программистом — короче говоря, ЛЮБОЙ;

• Общее количество элементов в массиве, например, [0..100] или [1..101] или [-50..50] что приведет к созданию массива с количеством в 101 элемент в любом из этих случаев, с той лишь разницей, что в первом случае элементы массива будут пронумерованы начиная с индекса (номера) 0 и заканчивая индексом 100, во втором случае с 1 до 101 и в третьем — с -50 до 50. Т. е. сам программист волен решать, как должны нумероваться элементы в создаваемом массиве.

Описание регулярного типа или массива имеет следующий общий вид:

где слова array и of — служебные, — имя типа массива (как вы хотите его назвать), T1 — тип индекса массива, которым может быть любой дискретный (целый) или ограниченный тип, модуль значений которого не может превышать число 65535, т. е. все целые типы кроме типа Longint (допустимы перечислимые типы), T2 — базовый тип элементов массива.

Вот примеры описания массивов:

В этом примере описана переменная Vector типа M1, который в свою очередь является массивом с элементами типа Real. Переменная Sys_Table моделирует некоторую логическую шкалу, в которой каждому символу (с типом Char) соответствует некоторое логическое значение. Доступ к элементам этого массива может быть организован так:

Переменные Arr1 и Arr2 типа Matrix, который является по сути двухмерным массивом 10x20 с типом Integer для каждого элемента массива. К элементам такого массива можно обращаться, например, так:

Впрочем, для описания типа массива Matrix можно использовать более простую форму:

Число индексов в определении массива (т. е. размерность) в языке не ограничивается, таким образом массив может быть как одномерный, так и двухмерный, трехмерный, четырех- и так далее. Красота :-)!

Переменная Customer имеет тип TCustomer, определяющий структуру данных в виде массива, каждый элемент которого является комбинированным типом — проще говоря, записью, состоящей из полей, которые могут содержать личную информацию о любом человеке (поля: Name — имя, Age — возраст, Address — адрес). К такому массиву можно обращаться так:

Переменная S описана как массив с индексами Red, Yellow, Green, перечислимого типа и элементами типа Boolean. Пример:

При работе с массивами необходимо помнить об ограничении на размер общей памяти под переменные. Чаще всего предел в 64 Кб бывает превышен из-за ошибочного описания массивов — последние либо состоят из чрезмерного количества элементов, либо эти элементы имеют большие размеры.

В авторской версии языка, а также в некоторых его реализациях имеется понятие упакованного массива, элементы которого хранятся в памяти максимально плотно, пусть даже в ущерб времени доступа к ним. Для задания таких массивов используется служебное слово packed, указываемое перед словом array, например:

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

Все приведенные выше примеры демонстрировали использование массива поэлементно. А как же использовать его целиком? Pascal допускает единственно возможное действие над массивом в целом — использование его в операторе присваивания, например:

причем типы обоих массивов в данном случае должны быть эквивалентны.

В качестве индексов могут выступать произвольные выражения, тип которых должен соответствовать типу индексов в описании массива.

Так, доступ к элементам массива Vector, описанного выше, можно строить следующим образом:

где — переменная целого типа.

Двухмерный массив Arr1, описанный выше, допускает такой доступ к своим элементам:

Поскольку его можно трактовать как «массив массивов», конструкция

вполне допустима в языке и в данном случае обозначает k-й массив в группе из 10 массивов. Для того чтобы адресоваться, скажем, к 5-му элементу этого массива, можно записать:

Такая запись корректна, хотя можно использовать более компактную форму

Каждый элемент массива считается переменной; он может получать значения (например, в операторе присваивания), а также участвовать в выражениях, где он представляет значение, помещенное в соответствующий элемент данного массива. Ассортимент операций над элементами массива полностью определяется типом этих элементов (базовым типом массива).

Примеры:

(Продолжение следует)

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov