7. Динамические структуры данных
Рассматриваемые до сих пор параметры программы обладали тем свойством, что под них выделяется вполне определенный размер памяти и между отдельными объектами устанавливаются связи еще на этапе компиляции и компоновки. Во время работы программы вносить изменения в выделенный размер памяти или установленные связи не удается. Порой это бывает неудобно. Например, программа работает с различным количеством целых чисел. Естественно разместить их в каком-то массиве. Размер массива должен быть определен заранее, и, если программа должна быть универсальной, при определении массива необходимо учитывать случай максимального количества таких чисел. Однако это приведет к неэффективному использованию оперативной памяти.
В языке Паскаль есть возможность по ходу выполнения программы выделять и освобождать необходимую память для размещения в ней различных данных. Таким образом можно организовывать динамические, т. е. изменяющие размеры,! структуры данных. Оперативная память при этом используется наиболее эффективным образом. Такая возможность связана с наличием в языке особых типов данных - указателей. Область оперативной памяти, где можно выделять отдельные участки для размещения данных и освобождать их, будем называть динамической областью памяти или динамической памятью.
Использование указателей является единственной возможностью увеличения объема глобальных параметров программы (см. п. 10) свыше 64 Кбайт.
7.1. Указатель
Указатель в Turbo Pascal дает адрес объекта определенного типа, называемого; базовым типом.
При определении типа-указателя используется этот базовый тип, перед кото-i рым ставится признак указателя ^.
Пример.
type |
|
Mas = array[1..10] of Real; |
{базовый тип} |
Point = "Mas; |
{тип-указатель на массив из 10 вещественных чисел} |
Переменная типа-указателя, которая в дальнейшем будет называться просто указателем, является физическим носителем адреса величины базового типа. Она занимает 4 байта памяти (2 слова). Первое слово дает смещение адреса, а второе - адрес сегмента. Значение этой переменной можно задать процедурой New или GetMem, использованием адресного оператора @, а также присваиванием ей значения другой переменной этого же типа. Переменной типа-указателя можно также присвоить значение nil, означающее отсутствие ссылки на какой-либо объект (фактически в этом случае переменной присваивается значение 0).
Пример.
type |
|
Complex = record |
{базовый тип} |
Re,Im: Real |
|
end; |
|
Point = ^Complex; |
{тип-указатель} |
AdrInt = ^Integer; |
{тип-указатель} |
var |
|
X: Complex; |
|
P1, P2, РЗ, Р4: Point; |
|
Ad1: AdrInt; |
|
. . . |
|
New(Pl); |
{выделение нового элемента типа Complex} |
Р2 : = @Х; |
{определение адреса переменной X} |
Р3 := Р1; |
{присвоение значения другого указателя} |
Р4 := nil; |
{присвоение значения nil} |
New(Ad1); |
{выделение нового элемента типа Integer} |
Следует иметь в виду, что указатели, ссылающиеся на объекты разных типов, сами являются объектами разных типов и для них недопустима операция присваивания значений друг другу. Указатели одного и того же типа можно сравнивать с помощью операций = и <>.
Чтобы получить значение элемента, с которым связан указатель, следует взять имя указателя и после него поставить знак ^.
Пример.
X := Р1^; |
{переменной X присваивается значение элемента, на который указывает Р1} |
Р3^ := X; |
{элементу, на который указывает Р3, присваивается значение переменной X} |
Стандартный тип-указатель Pointer дает указатель, не связанный ни с каким конкретным базовым типом. Этот тип совместим с любым другим типом-указателем, однако следует иметь в виду, что использование знака ^ после параметра типа Pointer дает параметр без типа (см. п. 10.3.4).
В Turbo Pascal существует операция получения адреса объекта - @, например
X:=@Y; {X - адрес параметра Y}
Полученный адрес в версии 7.0 может иметь конкретный тип или быть совместимым с любым указателем. Эти возможности зависят от использования ключа компилятора {$Т+/-} (см. п. 17.7.1).
|