Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции Все Разделы.docx
Скачиваний:
17
Добавлен:
21.09.2019
Размер:
607.75 Кб
Скачать
      1. Свойства статических массивов

Статические массивы характеризуются следующими свойствами:

  • постоянство структуры в течение всего времени ее существования,

  • смежность элементов и непрерывность области па­мяти, отводимой сразу для всех элементов структуры.

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

    1. Открытые массивы

В списке параметров, помещаемом в заголовках функций и процедур, допускается указывать массивы. Если размер воспринимаемого массива фиксирован, то в списке параметров тип такого параметра задается только с помощью идентификатора типа. Подпрограммы Object Pascal могут воспринимать также массивы, размер которых неизвестен. В этом случае в заголовке подпрограммы после записи имени параметра-массива указывается слово array, а затем базовый тип, а описание индексов не приводится. Например,

Procedure InverArray(D: Array Of Real;

Var T: Array Of Real);

Такие массивы (как D и T) называются открытыми массивами.

При таком определении массивов D и T тот массив, который передается в процедуру InverArray первым в качестве фактического параметра, будет копироваться в стек, и с этой копией  массивом D  будет работать процедура. Второй открытый массив (массив Т) определен как Var. Этот массив передается «по ссылке», т. е. он не копируется в стек, и процедура будет работать с тем массивом, который был передан в качестве фактического параметра при вызове InverArray.

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

    1. Динамические массивы

      1. Динамические векторы

Динамические массивы относятся к классу динамических структур. Физическое существование динамического массива реализуется в специальной области памяти, называемой куча (heap). Эта область предназначена для динамического распределения.

Динамические массивы отличаются от стандартных статических массивов тем, что в них не объявляется заранее число элементов. Поэтому динамические массивы удобно использовать в приложениях, где объем обрабатываемых массивов заранее неизвестен и определяется в процессе выполнения в зависимости от действий пользователя или объема обрабатываемой информации.

Объявление типа одномерного динамического массива, называемого также динамическим вектором, содержит только имя типа, ключевое слово array и идентификатор типа. Переменная типа «динамический вектор» объявляется обычным образом. Например, динамический вектор dinArr может быть объявлен следующим образом:

Type TdinVector = Array Of Real;

Var dinArr: TdinVector;

Если объявленный в секции Var статический массив размещается компилятором в памяти, то объявление динамического массива не приводит к отведению памяти для него. В памяти лишь резервируется 4‑байтовая ячейка, в которую будет занесен адрес динамически создаваемого участка памяти. Сам участок памяти для динамического массива создается при выполнении процедуры SetLength.

Для создания динамического вектора в функцию SetLength в качестве аргументов передаются имя массива и целая неотрицательная величина, значение которой равно количеству элементов создаваемого массива. Например, результатом вызова

SetLength(dinArr, 10);

будет выделение для вектора dinArr участка памяти под 10 элементов типа Real и задает всем элементам нулевые значения. Индексы динамического массива  всегда целые числа, начинающиеся с нуля. Поэтому в приведенном примере вектор состоит из элементов от dinArr[0] до dinArr[9].

Повторное применение SetLength к уже существующему массиву изменяет его размер. Если новое значение размера больше предыдущего, то все предыдущие значения элементов сохраняются, и в конце массива добавляются новые нулевые элементы базового типа. Если же новый размер меньше предыдущего, то массив усекается «справа» и в нем остаются значения начальных элементов. Усечение можно проводить функцией Copy, присваивая ее результат самому массиву, например, вызов

dinArr:= Copy(dinArr, 0, 3);

усекает динамический вектор dinArr, оставляя неизменными первые три его элемента.

Сама переменная динамического массива (в нашем примере это переменная dinArr) является указателем на начало массива. Если место под массив еще не выделено, значение этой переменной равно Nil. Операция сравнения А = В двух динамических массивов даст True только в том случае, если А и В указывают на один и тот же массив. Но это не совсем обычный указатель. Его нельзя, например, разыменовать операцией ^ , нельзя передать в процедуры New и Dispose.

Удалить из памяти динамический массив можно одним из следующих способов:

  • присвоить ему значение Nil, например, dinArr:= Nil;

  • использовать функцию Finalize: Finalize(dinArr);

  • установить функцией SetLength нулевую длину, например,

SetLength(dinArr, 0);

Динамические массивы могут передаваться в подпрограммы в качестве фактических параметров вместо формальных параметров, объявленных как открытые массивы.

Как указывалось выше, физическое существование динамического массива реализуется в специальной области памяти, называемой куча (heap). Эта область предназначена для динамического распределения. Поскольку одномерный динамический массив, как и статический, является последовательной структурой (т. е. участок памяти для массива непрерывен и слоты его элементов смежны), при изменении размеров массива можно наблюдать перемещение участка на новое место в куче. Например, пусть в программе записана следующая последовательность вызовов:

SetLength(D, 3);

SetLength(С, 4);

SetLength(D, 6);

где D и С  динамические векторы с одинаковым базовым типом. Тогда в результате выполнения второго вызова SetLength(С, 4) участок памяти для С будет создан сразу после участка вектора D, созданного при первом вызове SetLength(D, 3). Третий вызов должен увеличить участок для размещения нового вектора D. Поскольку новый участок должен превосходить старый вдвое, то «старых» ячеек ему будет недостаточно. Поэтому третий вызов приведет к появлению нового участка, содержащего смежные слоты элементов вектора D, и этот участок будет расположен после участка отведенного ранее для вектора С.