Вопросы для проверки знаний.

End.

Begin

End.

Begin

Inc(p1); { увеличение p1 на 4, поскольку одна величины типа longint занимает в памяти 4 байта}

p1:= @p2; { засылка в p1 указателя на указатель p2}

p2:= @L; { засылка в p2 указателя на величинуL}

L:= p1 - p2; { засылка в Lразности значений указателей }

p1:= p1 - 2; { уменьшение p1 на 2×4=8 байт}

p2:= p2 + 4; { увеличение p2 на 4×4=16 байт }

ПрисваиваниеL:= p1 - p2 в примере 6 возможно, поскольку все величиныL,p1,p2 занимают в памяти одинаковый объем - по 4 байта.

3.6.3. Выделение и освобождение динамической памяти

Динамические переменные создаются в динамической памяти (хипе) во время выполнения программы с помощью подпрограмм new (для типизированных указателей) или getmem(выделение нетипизированной памяти). Динамические переменные не имеют собственных имен, к ним обращаются через указатели. Выделение памяти и формирование указателей производится следующим образом.

1. Процедура new(var p:тип_указателя) выделяет в хипе участок размера, достаточного для размещения переменной того типа, на который ссылается указатель p, и адрес начала этого участка заносит в этот указатель.

2. Функция new(тип_указателя):pointer выделяет в хипе участок размера, достаточного для размещения переменной базового типа для заданного типа указателя, и возвращает адрес начала этого участка.

3. Процедура getmem(var p: pointer; size: word) выделяет в хипе участок размером в size байт и присваивает адрес его начала указателю p.

Если выделить требуемый объем памяти не удалось, программа аварийно завершается. Указатели могут быть любого типа.

Освобождение динамической памяти осуществляют с использованием процедур Dispose (при выделении памяти с помощью new) и Freemem- в противном случае.

4. Процедура Dispose(var p : pointer)освобождает участок памяти, выделенный для размещения типизированной динамической переменной процедурой или функцией new, и значение указателя p становится неопределенным.

5. Процедура Freemem (var p : pointer; size : word) освобождает участок нетипизированной памяти размером size, начиная с адреса, находящегося в p. Значение указателя после завершения действий становится неопределенным.

Если требуется освободить память из-под нескольких переменных одновременно, можно применять процедуры Mark и Release.

6. Процедура Mark(var p : pointer)записывает в указатель p адрес начала участка свободной динамической памяти на момент ее вызова.

7. Процедура Release(var p : pointer)освобождает участок динамической памяти, начиная с адреса, записанного в указатель p процедурой Mark.

Освобождение динамической памяти должно дополняться очисткой указателя на нее путем присваивания ему пустого значенияnil .

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

Пример 7 программы, в которой выполняется работа с динамическими переменными.

type pint = ^integer; { описание типа указателя pint на величины типа integer }

var p1, p2 : pint; { описание указателейp1,p2 на величины типа integer }

p3 : ^char; { описание указателяp3 на величины типа byte }

i:integer; ch:char; { описание переменной i типа integer и ch типа char }

new(p1); { выделение в хипе памяти для переменной типа integer,ссылка на нее - в указателеp1}

p2:=new(pint);{выделение памяти переменной integer, присвоениессылки на нее указателюp2}

new(p3); { выделение в хипе памяти для переменной типа char,ссылка на нее - в указателеp3}

p1^:=2; { присваивание динамической переменной по указателю p1значения, равного 2 }

i:=p1^+1; p2^:=(i+2)*5+2; { присваивание значения динамической переменной по указателю p2 }

ch:='A'; p3^:=ch; { присваивание значения динамической переменной по указателю p3 }

writeln('p1^=',p1^,' p2^=',p2^,' p3^=',p3^);{вывод динам. переменных по указат. p1-р3}

dispose(p1); p1:= nil;{освобождение памяти для динамической переменной по p1,очисткаp1}

dispose(p2); p2:= nil; {аналогичные действия для p2,p3}

dispose(p3); p3:= nil;

Использование указателей на подпрограммы рассмотрено в Главе 7.

1. В чем смысл введения указателей ?

2. Какие указатели называют стандартными, а какие типизированными ?

3. Каким образом указатели в Free Pascal могут задавать массив бесконечной длины ?

4. В чем заключается операция получения адреса переменной ?

5. В чем заключается операция разыменования ?

6. Гдесоздаютсядинамические переменные ?

7. В чем отличие применения подпрограмм new и getmemдля выделения динамической памяти ?

8. В чем отличие применения подпрограмм Dispose и Freememдля освобождения динамической памяти ?

9. Каким действием должно дополняться освобождение динамической памяти ?

4. Составной Оператор. понятия функции и процедуры.
Пользовательский интерфейс, Структура программ на языке Паскаль