Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка DELPHI.DOC
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.73 Mб
Скачать

Указатели

Как отмечено было выше, переменные могут располагаться или в статической или в динамической памяти. В первом случае под них выделяется вполне определённый размер памяти и связи между программными элементами устанавливаются на этапе компиляции и компоновки программы. Во втором случае память выделяется на этапе выполнения программы и может уничтожаться, повторно выделяться, что позволяет эффективно её использовать. При этом используется динамическая память – специально выделенная область оперативной памяти – Heap (куча).

К динамическим переменным относятся рассмотренные выше строки и динамические массивы, а также классы. Переменные данного типа называются ссылками. Работа со ссылками, в общем случае, отличается от работы с обычными переменными тем, что необходимо на каком-то этапе выполнения программы выделять память, а затем высвобождать её. Для строк память выделяется автоматически, автоматически строки (почти все типы) и уничтожаются. Это достигается довольно сложной структурой строки (кроме памяти под значение строки выделяется несколько байт для служебных целей). При работе с динамическими массивами приходится иногда (например, при присваивании) учитывать, что это ссылки. Для создания в программе собственных динамических переменных введён в язык Object Pascal тип указатель. Указателем иногда называют любую динамическую переменную.

Существуют стандартные указатели Pointer и типизированные указатели. Переменная-указатель – это переменная, которая хранит не сами данные, а адрес размещения этих данных. Указатели Pointer – это просто адреса без указания, что по этим адресам записано. Типизированные указатели содержат в себе ещё информацию о типе хранимых данных.

При объявлении типизированного указателя задаётся базовый тип данных. В этом случае компилятор легко определяет необходимый размер динамической памяти, который требуется выделить данному указателю. Объявление типизированного указателя записывается, например, следующим образом:

Type Mas=array [1..10] of real;

PtrMas=^Mas;

Var P:PtrMas;

Это же можно записать по-другому:

Var P:^array [1..10] of real;

Здесь объявлен указатель P, который является физическим носителем адреса расположения одномерного массива из 10 вещественных чисел.

В соответствии с объявлением указателя выделяется всего 4 байта статической памяти для записи адреса. Для записи данных вначале необходимо выделить динамическую память, её адрес записать в переменную-указатель и после этого размещать данные. Рассмотрим, как синтаксически это может быть записано. Объявим две переменные:

Var P1: ^Integer; D: Integer;

Теперь запишем:

New(P1); P1^:=5; D:=2+P1^; Dispose(P1);

Здесь первый оператор выделяет память, второй записывает число 5. Третий выполняет сложение с содержимым выделенной динамической памяти. Четвёртый освобождает занятую память.

Указателю можно присваивать значение nil – пустой адрес, например, P1:=nil;

Для задания значения указателю можно воспользоваться операцией взятия адреса, например, P1:=@D;

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

Стандартный указатель объявляется, например, так:

Var PP:Pointer;

Память под этот указатель выделяется с помощью следующей процедуры: GetMem(PP, 20);

Здесь выделено 20 байт динамической памяти. Эту процедуру можно использовать и для выделения памяти под типизированные указатели, например, для объявленного выше указателя P:

GetMem(P, SizeOf(Mas));

Функция SizeOf(T) используется для указания размера базового типа для переменной-указателя, здесь T – базовый тип данных. Если память выделена процедурой GetMem(<указатель>, Size), то для освобождения памяти используется процедура FreeMem(<указатель>, Size). Например, FreeMem(P, SizeOf(Mas));

К указателям применимы две операции сравнения равно и не равно. Возможно присваивание их друг другу, например, если объявлено:

Var P1, P2: ^double; P3: Pointer;

то возможны присваивания: P2:=P1; или P3:=P2;

Нельзя присваивать P2:=P3, так как переменная P2 требует задания базового типа, а P3 его не имеет. Присваивание P3:=P2 происходит с потерей информации о базовом типе.

Для проверки значения указателя на неравенство nil можно использовать функцию Assigned(<указатель>). Эта функция возвращает true, если значение указателя не равно nil. В модулях System и SysUtils размещены различные стандартные подпрограммы работы с указателями и динамической памятью.

Рассмотрим, каков синтаксис присваивания значений элементам массива P, объявленного выше.

New(P); P^[1]:=6.7; P^[2]:=-3.5; и т.д.

По окончании работы с массивом занятую память нужно освободить: Dispose(P);