Використання вказівників типу pointer дозволяє узгодити поля пам'яті різних типів. Це один із способів перетворення типів. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Використання вказівників типу pointer дозволяє узгодити поля пам'яті різних типів. Це один із способів перетворення типів.



Взагалі операції присвоєння між вказівниками можливі між однаковими або еквівалентними типами.

VAR

Pi1:Pint;

Pi2:^integer;

PPi1:PPint;

PPi2:^Pint;

Pc1:Pchar;

Pc2:^char

............

Pi1:=PPi1;

Pi1^:=PPi1^; {не можливі}

Pi1:=Pc1;

Pi1^:=Pc!^;

Pi1:=Pi2;

Pi1^:=Pi2^;

PPi1:=PPi2; {можливі}

Pc1:=Pc2;

Pi1:=PPi1^

Як вже відмічалося значення вказівного типу є чотирибайтні числа. формально ці числа розділяються на дві частини по 2 байти: старше, менше слово. Старше слово є адресою початку сегменту; молодше слово – зміщення комірки пам'яті від початку сегмента.

Із усіх можливих значень, які існують, особливе значення має nil, що означає вказівник „в нікуди”. Цей вказівник не співпадає із 1 Мб з жодним і фактично є абстрактним поняттям. Реально в пам'яті такої комірки немає. Значення nil – це не нуль для цілих чи дійсних чисел.

Будь-який із вказівників може набувати значення nil, проте не можна застосовувати операцію розіменування вказівника, оскільки nil не вказує на якусь конкретну ділянку пам'яті.

Тема: Динамічні змінні.

Застосування вказівників дозволило реалізувати особливий вид змінних – динамічних.

На відмінну від іншого виду змінних (статичні), які існують протягом всього часу виконання програми, динамічні змінні можуть створюватися і знищуватися в будь-який момент програми спеціальними програмами.

Статичні змінні - це всі змінні, що оголошені в розділі var незалежно від типу. Ці змінні розміщуються в спеціальному сегменті пам'яті, що називають статичною пам’яттю або програмним стеком (не більше 64 Кб). Ці змінні слідують в порядку оголошення у програмі. Вони з'являються на початку виконання програми і стек звільняється при завершені програми.

Враховуючи, що стек не перевищує 1 сегменту пам'яті, а отже кількість статичних змінних буде обмежена.

Динамічні змінні розміщуються в особливій частині оперативної пам'яті, що називається динамічною пам’яттю, або Heap-областю, або кучею. Під кучу відводиться вся вільна на момент виконання програми пам'ять. Враховуючи, що перших 360 Кб базової пам'яті займає ОП, то максимальний розмір буде 640 Кб.

Реально всі програми, які виконуються паралельно із Pascal-програмою теж частково використовують оперативну пам'ять.

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

Для створення і знищення динамічних змінних є три групи підпрограм:

NEW (var p:point); DISPOSE(var p:pointer).

MARK (var p:pointer); RELASE (var p:pointer).

GETMEM (var p:pointer; size:longint); FREEMEM (var p:pointer; size:longint).

Перші процедури в кожній групі створюють динамічні змінні; другі – знищують. Використання кожної із груп процедур визначається потребами програми, оскільки результати їх роботи відмінні.

При створенні динамічних змінних процедурою New, в якості фактичного параметра використовується статична змінна вказівного типу.

VAR

Pi1:Pint;

Ppi1:PPint;

Pc:Pchar;

Ps:^string;

BEGIN

New(Pi1);

New(PPi1);

New(Pc);

New(Ps);

END.

Тут створюється 4 динамічних змінних, на які є статичні вказівники. Перша динамічна змінна матиме тип integer, друга – вказівний тип на integer, третя – тип char, четверта – тип string.

Динамічні змінні розміщуються у пам'яті не неперервним чином, а, починаючи з кожного нового 8 б блоку. Таким чиною створення динамічних змінних малих розмірів є малоефективним, оскільки з користю використовується 1\8, 1\4.

Якщо динамічна змінна створена процедурою New, то знищення можна провести лише відповідною Dispose. Відповідна ділянка кучі звільнюється, а параметр вказівника втрачає своє значення.

При звільненні частини кучі процедурою Dispose з'являються вільні фрагменти пам'яті можливо достатньо великого розміру. Чи будуть при новому створені динамічні змінні розміщуватися в звільнених ділянках? При новому створені, динамічні змінні розміщуються, починаючи з першого 8-мибайтного блоку після останньої динамічної змінної в мові Рascal завжди рівне адресі початку першого 8-мибайтного блоку після останньої динамічної змінної в кучі: Heap ptr.

Всі новостворені динамічні змінні розміщуються, починаючи з адреси Heap ptr. Після кожного нового створення Heap ptr збільшує своє значення.

Друга група підпрограм для створення динамічних змінних оперує лише з динамічними змінними типу pointer і розміром цієї змінної 4 байти.

В якості інформаційної комірки використовувати її малоефективно.

При створені динамічних змінних процедурою Mark(р), її параметр типу pointer отримує значення вказівника Heap ptr. Таким чином змінна р фіксує стан динамічної пам'яті процедурою Mark.

Після фіксації стану, в ній можуть бути створені або знищенні динамічні змінні попередніми процедурами, при цьому вказівник Heap ptr буде отримувати нове значення. Повернутися до зафіксованого раніше процедурою Mark значення Heap ptr можна процедурою Release(p) з цим самим значенням. При цьому не відбувається знищення чи добавлення даних до зафіксованого значення.

Всі динамічні змінні, що знаходяться вище цього значення будуть вважатися знищеними. Виникає питання: що буде в наступній ситуації.

 

New(p1);

New(p2);

Mark(p);

Dispose(p1);

Dispose(p2);

Release(p);

Така ситуація не відновлює дані, хоча Heap ptr вказує на вершину раніше зайнятої кучі. Утворюються пустоти, в яких не вдасться розмістити нові динамічні змінні.

При розміщенні динамічних змінних у пам'яті, потрібно враховувати, що неможливість чергової операції створення динамічної змінної із-за відсутності місця в кучі, призводить до зупинки програми, тому потрібно контролювати стан динамічної пам'яті на наявності вільного простору. Для цього Pascal має стандартні функції без параметрів.

MemAvail:longint;

MaxAvail:longint;

MemAvail повертає своїм значенням загальний розмір вільної пам'яті в перерахунку на 8-мибайтні блоки. Цей розмір видається в байтах.

MaxAvail повертає своїм значенням розмір максимальної неперервної вільної ділянки в кучі в перерахунку на 8-мибайтні блоки. Таким чином при операціях багатократного створення динамічних змінних варто користуватися наступною перевіркою

if MaxAvail>=sizeof(<базовий тип>) then New(…)

else writeln(‘немає місця’);

Тема: Динамічні структури даних.

Використання вказівники та динамічних змінних дозволяє будувати нові структури даних, які називаються динамічними. Вони розміщуються в динамічній частині пам'яті і можуть як завгодно змінювати свій розмір, тобто кількість елементів, таким чином дечим подібні до типізованих файлів, які теж можуть змінювати свій розмір. Проте є деякі принципові відмінності:

Файли розміщуються в зовнішній пам'яті, а динамічні структури в оперативній.

Типізовані файли фактично є файлами прямого доступу, що означає довільний доступ до елементів. В динамічних структурах доступ до елементів виключно послідовний.

Зв’язок між елементами в динамічних структурах реалізуються при допомозі вказівників, кожен елемент такої структури в свою чергу є складеною структурою: інформаційна частина містить корисні дані, а вказівна містить адресу наступного елемента.

Тема: Списки. Атрибути списків.

Згадані вище динамічні структури даних в програмуванні називають списками. Під списком розуміється деяка послідовна структура даних, кожен елемент якої містить два компоненти: інформаційне поле та вказівні поля. Саме через вказівники здійснюється зв’язок елементів у списку.

Доступ до всього списку реалізується через фіксований вказівник у вигляді статичної змінної на перший елемент списку – голова списку. Всі решта елементів утворюють так званий хвіст списку. Останній елемент списку переважно вказує в nil – це є ознака кінця списку.

В залежності від кількості вказівних полів в кожному елементі списку, розрізняють однозв’язні списки (один вказівник) п-зв’язні списки (п вказівників).

Крім такого поділу по зв’язності, списки бувають лінійними, деревами, графами та ін.

В двонапрямлених списках доступ до елементів однаково здійснюється при русі від першого до останнього за вказівником next, або від останнього до першого за вказівником prev.



Поделиться:


Последнее изменение этой страницы: 2016-09-19; просмотров: 230; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.118.19.162 (0.014 с.)