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

Динамічні масиви

Розмір кожного з розділів програми (коду, кожної з підключе­них бібліотек, статичної або автоматичної пам'яті) не може пере­вищувати 64 кілобайт. Якщо для розв'язання задачі потрібні дані більшого розміру, їх можна розміщувати у вільній пам'яті. Про­те розмір неперервної ділянки пам'яті не може бути більшим ніж 64 кілобайт, тому за необхідності пам'ять виділяють части­нами по 64 кілобайти.

Розглянемо дві процедури, які використовуються для роботи з масивами в купі. Процедура getmem має два параметри — безтиповий вказівник і розмір типу word. Вона резервує ділянку вільної пам'яті заданого розміру й установлює на неї вказівник.

Наприклад, якщо р має тип Pointer, то після виконання вик­лику getmem (р, 10000) вказівник р установлено на ділянку купи розміром 10 000 байт.

Звільнення ділянки заданого розміру, на яку встановлено вказівник, виконується процедурою f reemem.

Наприклад, freemem (p, 10000) означає звільнення «з-під р» ділянки розміром 10 000 байт. Розмір звільненої ділянки має до­рівнювати розміру виділеної, інакше можливі непередбачені на­слідки.

Максимальний розмір, який можна указати у викликах підпрограм getmem і freemem у системі Turbo Pascal, дорівнює 65 528 байт.

Масив у купі позначають вказівником, установленим на його перший елемент. В оголошенні типу масиву задають тільки індекс і тип його першого елемента, наприклад:

type aLong=array[0..0] of longint.

Тип вказівників на масиви цього типу оголошується як paLong=^aLong.

Зарезервована ділянка пам'яті обробляється як змінна типу Т за допомогою безтипового вказівника, перетвореного на тип ^Т. Перетворений вказівник задають виразом вигляду ^Т (ім'я-вказівника).

Приклад. Якщо р — безтиповий вказівник, то вираз paLong (р) позначає вказівник р, перетворений на тип вказів­ників на масиви елементів типу longint (оголошення типу paLong наведено вище). Значенням виразу є адреса першого байта ділянки пам'яті, на яку вказує р. Якщо ця ділянка має розмір 65 528, вона є масивом з 16 382 (тобто 65528/sizeof (longint)) елементів типу longint.

Елемент масиву з індексом k, де 0 < k < 16381, задається ви­разом вигляду paLong(р)^[k].

Якщо масиву розміром 65 528 байт недостатньо, можна утво­рити кілька динамічних масивів.

Приклад. Створимо масив елементів типу longint «блоками» по 16 382 елементи, тобто по 65 528 байт, присвоїмо елементам їх порядкові номери та для демонстрації виведемо на екран зна­чення елементів, індекси яких кратні 10 000. Під кінець звільни­мо зайняту пам'ять.

Для розв'язання цієї задачі оголосимо типи масивів та вказів­ників на них.

aLong = array[0..0] of longint; paLong = ^aLong;

Максимальна кількість блоків blocks нехай дорівнює 9. Ого­лосимо масив вказівників

p: array [0..blocks-1] of pointer і кількість елементів у блоці num=16382.

За допомогою процедури getmem виділимо ділянки пам'яті розміром size=num*sizeof (longint) байт і на них установи­мо вказівники масиву р.

Якщо виділити нову ділянку неможливо через брак пам'яті, процес виділення припинимо.

Якщо виділено count блоків, то масив має num*count еле­ментів. Елемент з індексом k, де 0 < k < num*count-l, задано виразом:

paLong(p[k div num])^[k mod num].

І навпаки, paLong (p[i]) ^ [j], де 0 < і < count-1, задає еле­мент масиву з індексом num*i+j.

program array_of_pointers;

const blocks=9; {максимальна кількість блоків}

num=16382; {кількість елементів блока}

type aLong=array[0..0] of Longint; {тип масиву}

paLong=^aLong; {тип вказівників на масиви}

{масив вказівників на блоки}

var р:array[0..blocks-1] of pointer;

totnum, {загальна кількість елементів}

к, {лічильник елементів}

count, сс, {лічильники блоків}

size:longint; {розмір блока}

begin

{виділення пам'яті блоками}

size:=num*sizeof(longint); сс:=0;

while (cc<blocks) and (size<=maxavail) do begin

getmem(p[cc],size); cc:=cc+l;

end;

count:=cc; {виділено count блоків,}

totnum:=num*count; {в них totnum елементів}

wrіteln('Елементів у масиві: ', totnum);

{присвоювання значень елементам масиву}

for k:=0 to totnum-1 do

paLong(p[k div num])^ [k mod num]:=k;

{виведення на екран елементів,}

{індекси яких кратні 10000}

k: =0 ;

while k<=totnum-1 do begin

writeln(paLong(p[k div num])^[k mod num]:7);

inc (k,10000)

end;

{звільнення зайнятої пам'яті}

for cc:=0 to count-1 do freemem(p[cc],size);

end.