- •Адреси та вказівники
- •Вільна пам'ять
- •Динамічні масиви
- •Поняття динамічного лінійного списку
- •If not (s належить sqs) then
- •V : string;
- •Створення та обробка списку
- •Var p : pElem; begin
- •Var f:text; {вхідний текст}
- •If not isIn(s,h) {якщо рядка в списку немає}
- •Var sqs:pElem; {вказівник на голову списку}
- •Вилучення елемента списку
- •Var p:pElem; {допоміжний вказівник}
- •Var p:pElem; {допоміжний вказівник}
Динамічні масиви
Розмір кожного з розділів програми (коду, кожної з підключених бібліотек, статичної або автоматичної пам'яті) не може перевищувати 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.
