Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры и алгоритмы обработки данных.doc
Скачиваний:
348
Добавлен:
12.03.2015
Размер:
1.81 Mб
Скачать

1.3. Дополнительные вопросы использования переменных-указателей

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

var x : real; {обычная переменная вещественного типа}

pReal : ^real; {указатель на вещественный тип}

begin

x := 1.5; {обычная переменная x получает значение 1.5}

pReal := @x; {указатель получает адрес размещения числа 1.5}

Write(pReal^ : 6 : 2); {вывод числа 1.5 с помощью указателя pReal}

end;

Принципиальное отличие данного способа использования указателя от ранее рассмотренного состоит в том, что здесь НЕ используется механизм динамического распределения памяти, т.е. НЕ используются стандартные функции New и Dispose: переменная x является обычной статической переменной, размещаемой в статической области памяти, просто доступ к ней по каким-то причинам организуется не напрямую, а с помощью ссылочной переменной.

Довольно мощным использованием указателей является объединение их в массив. Это можно сделать в силу того, что все переменные-указатели с одним и тем же базовым типом являются однотипными. Массивы указателей можно обрабатывать с помощью циклов. В качестве примера рассмотрим массив указателей на записи некоторой структуры.

type TRec = record {описание базового типа-записи}

x, y : integer;

name : string;

end;

TpRec = ^TRec; {описание ссылочного типа}

var ArrOfPointer : array[1..100] of TpRec;

{объявление массива указателей на записи}

begin

for i := 1 to 100 do ArrOfPointer [ i ]^.x : = Random(100);

{цикл установки значений в поле x}

end.

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

var pAll : pointer;

Распределение и освобождение памяти для нетипизированных указателей производится с помощью специальных стандартных функций GetMem и FreeMem, которые имеют по два параметра – имя нетипизированного указателя и байтовый размер выделяемой области памяти. Для задания этого размера удобно использовать стандартную функцию SizeOf, которая принимает имя типа данных, а возвращает необходимый размер области памяти. Например:

type TRec = record {описание базового типа-записи}

x, y : integer;

name : string;

end;

var p1, p2 : pointer; {объявление двух нетипизированных указателей}

begin

GetMem ( p1, SizeOf ( TRec ) ); {распределение памяти под объект-запись}

p1^.name := ‘Text’;

p2 := p1; {оба указателя адресуют одну и ту же область}

FreeMem ( p1, SizeOf ( TRec ) );

{освобождение памяти и деактуализация указателя p1}

end.

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