Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по курсу.docx
Скачиваний:
107
Добавлен:
24.02.2016
Размер:
2.8 Mб
Скачать

8.2. Понятие указателя

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

Вводятся указатели следующим образом:

Type

Рк=Атип;

Pi=Aarray[1..20] of integer; Pb=Abyte;

Ps=AString [20];

Var

p,q:pointer; a,b:Pk;

i:Pi k:Pb;

S1,S2:Ps;

Здесь р, q - нетипизированные указатели; а, b, i, k, S1, S2 - типизи­рованные указатели, т.е. они указывают, что, например, в ячейках начиная с адреса а размещается переменная указанного типа Pk.

Значениями указателей являются адреса переменных, размещенных в памяти. Значение одного указателя можно передать другому с помощью опе­ратора присваивания, например:

p:=q;

a:=b;

При этом надо помнить, что в операторе присваивания типизированные указатели должны быть одного типа.

Используя нетипизированные указатели, можно передать адрес между указателями разного типа, например, так:

p:=i; k:=p;

С типизированными указателями можно работать как с обычными пе­ременными следующим образом:

S1A:=,Иванов,; // по адресу S1 разместить строку iA[11]:=88;

kA:=25;

m:=iA[9]+kA; // m - целого типа

Указатели одного типа можно сравнить на предмет равенства = и нера­венства < >, например: if a=b then ... или if a<>b then...

Следует заметить, что такие действия возможны лишь после того, как самим указателям S1, i, k, a, b будут присвоены конкретные значения (адре­са).

Адрес указателю можно присвоить следующим образом: Если m, n - обычные статические переменные, то ее адрес можно полу­чить с помощью специальной функции p:=Addr(m); a:=Addr(n);

Очистка адреса из указателя осуществляется с помощью специальной функции nil: p:=nil; a:=nil, при этом довольно часто используется проверка условия if p<>nil then ...

8.3. Наложение переменных

Использование указателей позволяет «накладывать» переменные раз­ных типов друг на друга, интерпретируя по-разному данные, расположенные по некоторому адресу. Например:

Var Ch:Char; k:Abyte;

k:=Addr(ch);

Ch:='A';

Write(Ch,kA);

Будет выведен сам символ 'А' и его номер в кодовой таблице 65. Следующий пример иллюстрирует наложение одномерного массива на двухмерный:

Var a:Aarray[1..4] of integer;

b:array[1..2,1..2] of integer;

a:=Addr(b);

for i=1 to 4 do aA[i]:=i;

Write('b[1,2]=',b[1,2]); // будет выведен): b[1,2]=2 Такое наложение может быть полезно использовано, например, при вводе матрицы иногда удобнее использовать один индекс, а при вычислениях работать с двумя индексами.

8.4. Динамическое распределение памяти

Вся свободная от программ память компьютера представляет собой массив байтов, который называется кучей. Когда возникает необходимость использования программой дополнительной памяти, это осуществляется од­ной из процедур New или GetMem.

Процедура

New(a:<типизированный указатель>);

находит в куче свободный участок памяти, размер которого позволяет разместить тип данных а и присваивает указателю а значение адреса первого байта этого участка. После этого данный участок памяти закрепляется за про­граммой и с ним можно работать через возникшую в программе переменную aA. Такие переменные называются динамическими. После того, как необхо­димость работы с этой переменной отпала, данный участок памяти освобож­дается с помощью процедуры Dispose(a);

При работе как с типизированными, так и с нетипизированными указа­телями аналогичные действия выполняют процедуры GetMem(P:pointer; size:Word); FreeMem(P:pointer; size:Word); здесь size - количество байтов выделяемой памяти, начиная с адреса, помещаемого в указатель Р. Следует помнить, что память под указатель вы­деляется 8-байтными порциями. В результате возможна нежелательная фраг­ментация.