Главная » Delphi » Указатели Delphi

0

Указатель (pointer) представляет собой переменную, содержащую  местоположение (адрес) участка  памяти. В этой  главе  уже встречался указатель, когда рассматривался тип PChar. Тип указателя  в Object  Pascal называется Pointer, или нетипизированный указатель, поскольку  он содержит адрес  определенного места  в памяти, а компилято ру ничего не известно о данных, располагающихся по этому адресу. Но  применение таких  “указателей  вообще”  противоречит  концепции строгого контроля типов, по этому в основном придется работать с типизированными указателями, т.е. с указате лями на данные  конкретного типа.

НА ЗАМЕТКУ

Указатели — тема достаточно сложная для новичка, а приложения Delphi можно соз-

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

Delphi.

Типизированные указатели  объявляются в разделе Type программы с использова нием  символа  ^ (оператора указателя) или  ключевого слова  Pointer. Типизирован ные  указатели  позволяют компилятору отслеживать, с каким  именно типом  данных происходят действия и не выполняются ли при этом некорректные операции. Вот примеры объявлений типизированных указателей:

Type

PInt = ^Integer;            // PInt – указатель на Integer

Foo = record                // Тип  – запись

GobbledyGook: string;

Snarf: Real;

end;

PFoo = ^Foo;                // PFoo – указатель на объект типа foo

var

P: Pointer;

//

Нетипизированный указатель

P2: PFoo;

//

Экземпляр PFoo

НА ЗАМЕТКУ

Программисты на языке C++ могут заметить схожесть оператора ^ Object Pascal и оператора * языка C++. Тип Pointer в Object Pascal соответствует типу void * языка C.

Запомните, что переменная типа Pointer всегда содержит только  адрес области па мяти.  О выделении памяти для структуры, на которую  будет указывать  такой  указатель, программист должен  позаботиться сам (для этого  можно  воспользоваться одной  из функций, перечисленных в табл. 2.6).

НА ЗАМЕТКУ

Когда указатель не указывает ни на что (его значение равно 0), то о таком указателе говорят, что его значение равно Nil, а сам указатель называют нулевым, или пустым указателем.

Если  необходимо получить  доступ  к данным, на  которые указатель  указывает,  то можно  воспользоваться оператором ^, следующим  за именем этой  переменной. Такой метод  называется разрешением указателя (dereferencing), а также  косвенным доступом, взя тием значения, разыменованием и ссылкой. Ниже приведен пример работы с указателями.

Program PtrTest;

Type

MyRec = record

I: Integer;

S: string;

R: Real;

end;

PMyRec = ^MyRec;

var

Rec: PMyRec;

begin

New(Rec);           // Выделить память для новой записи Rec

Rec^.I := 10;       // Поместить в нее данные. Обратите внимание

// на оператор ^

Rec^.S := ‘And now for something completely different.';

{ Теперь помещаем в нее данные другого типа }

Rec^.R := 6.384;

{ Теперь запись Rec заполнена }

Dispose(Rec);       // Не забывайте освобождать память!

end.Когда использовать функцию New()

Функция New() используется при выделении памяти для указателя на структуру дан- ных известного размера. Поскольку компилятору известен размер структуры, для кото- рой необходимо выделить память, то при выполнении функции New() будет распре- делено достаточное количество байтов, причем такой способ выделения более кор- ректен и безопасен, чем вызов функции GetMem() или AllocMem(). В то же время, никогда не используйте функцию New() для выделения памяти для типов Pointer или PChar, так как в этом случае компилятору не известно, какое количество памяти долж- но быть выделено. И не забывайте использовать функцию Dispose() для освобожде- ния памяти, выделенной с помощью функции New().

Для выделения памяти структурам, размер которых на этапе компиляции еще не из-

вестен, используются функции GetMem() и AllocMem(). Например, компилятор не может определить заранее, сколько памяти потребуется выделить для структур, зада- ваемых переменными типа PChar или Pointer, что связано с самой природой этого типа  данных.  Самое  важное —  не  пытаться  манипулировать количеством  памяти, большим, чем было выделено реально, поскольку наиболее вероятным результатом таких действий будет ошибка доступа к памяти (access violation). Для освобождения памяти, выделенной с помощью вышеупомянутых функций, используйте функцию FreeMem(). Кстати, для выделения памяти лучше пользоваться функцией Al- locMem(), так как она всегда инициализирует выделенную память нулевыми значе- ниями.

Один  из аспектов работы с указателями в Object  Pascal,  который существенно от личается от работы с ними  в языке  C, — это их строжайшая типизация. Так,  в приве денном  ниже примере переменные a и b не совместимы по типу.

var

a: ^Integer;

b: ^Integer;

В то же время в эквивалентном описании на языке C эти переменные вполне со

вместимы:

int *a;

int *bObject  Pascal  создает  уникальный тип  для  каждого  объявления указателя на тип (pointer to type),  поэтому  для совместимости по типу следует объявлять не только  пе ременные, но и их тип:

type

PtrInteger = ^Integer;      // Создать именованный тип

var

a, b: PtrInteger;           // Теперь a и b совместимы по типу

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии