Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
R11_ДЗ_12.doc
Скачиваний:
2
Добавлен:
22.12.2018
Размер:
809.98 Кб
Скачать

Динамічний розподіл пам’яті

Виділенням та звільненням динамічної пам’яті керують оператори new та delete.

Формати оператора new:

new <тип>;

new (<тип>);

new <тип>[<вираз>];

Вираз визначає розмір виділеної пам’яті заданого типу даних

int *r=new int;

float *r=new (float);

float *r=new float [20];

Якщо пам’ять виділена оператором new, то вона звільняється оператором

delete <покажчик> або delete []<покажчик>

Застосування delete до покажчика, отриманого не за допомогою new, не визначено.

Наприклад,

#include <stdio.h>

#include <conio.h>

main ( )

{ int *pi=new int;

*pi=30;

printf("adres %p, content %d\n",pi,*pi);

delete pi;

pi=new int[5];

for(int i=0;i<5;i++)

{ pi[i]=i*4;

printf("adres %p, content %d\n",pi[i],pi[i]);

}

delete[]pi;

getch();

}

Динамічні структури даних

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

Списки

Важливим аспектом використання динамічних змінних є обробка спискових структур даних.

Список – це сукупність логічно зв'язаних елементів, кожен з яких окрім інформаційної частини містить посилання на наступний або (та) попередній елемент списку.

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

Розрізняють:

  • Лінійний однозв'язний список - структура, кожен елемент якої містить посилання, що зв'язує його з наступним елементом.

Різновиди:

  • Черга - структура, у якій елементи обробляються за принципом FIFO («першим прийшов - першим пішов»). Початок списку зберігається в окремій змінній (first). Критерієм закінчення списку є наявність у полі Next останнього елемента значення nil.

  • Стек - структура, у якій елементи обробляються за принципом LIFO («останнім прийшов - першим пішов»).

  • Лінійний двозв'язний список - структура, кожен елемент якої містить два посилання: на наступний і на попередній елементи списку.

  • Кільцевий список - структура, у якої останній елемент зв'язний з першим.

Дерева

Дерево (нелінійний список)- структура, кожен елемент якої зв'язний з декількома іншими.

Розрізняють

  • бінарні дерева – з кожним вузлом зв'язано два елемента;

  • збалансовані дерева – з кожним вузлом зв'язана однакова кількість елементів;

  • незбалансовані дерева – з кожним вузлом зв'язана різна кількість елементів.

Зазвичай, елементами списку є записи.

Оголошення списку може мати вигляд:

Type

TPtr = ^ Elem;

Elem = record

Inf : string [30];

Next : TPtr;

end;

Var First, Nov, Tek : TPtr;

Введення

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

  • сама програма користувача;

  • системні програми часу виконання, які здійснюють допоміжні дії при роботі програми користувача;

  • визначені користувачем структури даних і константи;

  • точки повернення для програм;

  • тимчасова пам'ять для зберігання проміжних результатів при обчисленні виразів;

  • тимчасова пам'ять при передачі параметрів;

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

  • різні системні дані (інформація про статус пристроїв введення-виведення та ін.)

З цього переліку видно, що управління пам'яттю стосується широкого класу об'єктів.

У Turbo Pascal існує можливість прямого доступу до будь-якого байту оперативної пам'яті на його адресу за допомогою визначених у модулі system масивів Mem, MemW і MemL, які дозволяють записати інформацію або прочитати її безпосередньо з комірок пам'яті (один, два або чотири байти). Це дуже небезпечні дії, тому вони виключені в 32 - розрядних системах програмування. Все ж таки дамо короткі пояснення для тих, хто працює в середовищі Borland (Turbo) Pascal.

Наприклад, початкова адреса відеобуфера запишеться у вигляді $ B800: $ 000, а звернутися до самого першу його байту можна так: Mem [$ В800: $ 0000], до перших двох байтам - MemW [$ B800: $ 0000], до перших чотирьох байтам - MemL [$ B800: $ 0000]. Абсолютний адреса, що відповідає даній парі, -- $ B8000.

Ще один приклад для допитливих - оператор mem [0: $ 41C]: = mem [0: $ 41А]; можна застосувати для примусової очищення буфера клавіатури. Тут адреса маркера кінця буфера клавіатури прирівнюється до адреси його початку. Звичайно, в даному випадку краще скористатися засобами модуля crt.

Є ще один спосіб звернення до оперативної пам'яті - Використання службового слова absolute при описі змінної. У цьому випадку змінна буде розташовуватись саме за тією адресою в оперативній пам'яті, який вказаний після absolute. Зрозуміло, використання службового слова absolute - настільки ж небезпечний спосіб, як і звернення до пам'яті через зумовлені масиви.

Однак absolute може використовуватися і більше безпечним способом, дозволяючи поєднувати в пам'яті дві змінні з різними іменами.

Приклад. Дан текстовий файл розміром не більше 64 Кб, що містить дійсні числа, за одному в кожному рядку. Переписати вміст файлу в масив, розмістивши його в динамічно розподіляє пам'яті. Обчислити середнє значення елементів масиву. Очистити динамічну пам'ять. Створити цілий масив розміром 10000, заповнити його випадковими цілими числами в діапазоні від -100 до 100 і обчислити його середнє значення.

(Мова Turbo Pascal)

Program Srednee;

Const NMax = 10000;

Type Diapazon = 1 .. NMax;

MasInt = Array [Diapazon] Of Integer;

MasReal = Array [Diapazon] Of Real;

Var PIint: ^ MasInt; PReal: ^ MasReal;

I, Midint: longInt; MidReal: Real; T: Text; S: string;

Begin

Write ( 'Введіть ім'я файлу:'); ReadLn (S);

Assign (T, S); Reset (T); MidReal: = 0; MidInt: = 0;

Randomize;

NEW (PReal); (Виділення пам'яті під речовинний масив)

(Введення і підсумовування речового масиву)

While Not Eof (T) Do

Begin ReadLn (T, PReal ^ [I]); MidReal: = MidReal + PReal ^ [I] End;

DISPOSE (PReal); (Видалення речового масиву)

NEW (PInt); (Виділення пам'яті під цілий масив)

(Обчислення і підсумовування цілого масиву)

For I: = 1 To NMax Do

Begin PInt ^ [I] : = -100 + Random (201); MidInt: = MidInt + PInt ^ [I] End;

(Виведення середніх значень)

WriteLn ( 'середнє ціле одно:', MidInt Div NMax);

WriteLn ( 'середнє речовий одно:', (MidReal/NMax): 10: 6)

End.

// Мова C + +

# include

# include

# include

# include

# define NMax 10000

typedef int MasInt;

typedef float MasReal;

MasInt * PInt; MasReal * PReal;

int I, n, MidInt; float MidReal; char S [255];

FILE * t; char * endptr;

void main ()

(cout << "Введіть ім'я файлу:"; cin>> S;

t = fopen (S, "r ");

MidReal = 0; MidInt = 0;

randomize (); I = 0;

/* Виділення пам'яті під речовинний масив */

PReal = (MasReal *) malloc (sizeof (MasReal ));

/* Введення і підсумовування речового масиву */

while (! feof (t))

(fgets (S, 255, t);// вводимо з файлу рядок

PReal [I] = strtod (S, & endptr);// перетворимо введену рядок у дійсне число

MidReal + = PReal [I]; I ++;}

n = I +1;

free (PReal);/* Видалення речового масиву */

PInt = (MasInt *) malloc (sizeof (MasInt)); / * Виділення пам'яті під цілий масив */

/* Обчислення і підсумовування цілого масиву */

for (I = 0; I < NMax; I ++)

( PInt [I] = -100 + random (201);

MidInt + = PInt [I ];}

/* Висновок середніх значень */

cout << "nсреднее ціле одно" <<< "n";

cout << "середнє речовий одно: "<<<" n ";

fclose (t);

)

Функція Ptr перетворить свій аргумент-адресу в значення вказівника, наприклад:

P1:=Ptrt($1234,$4567);

При програмуванні на мові Pascal для розміщення динамічних змінних використовується область пам'яті з назвою Heap або «куча». Розмір Heap можна регулювати за допомогою директиви компілятору $М або задати при налагодженні середовища (Option/Compiler/Memory size) від 0 до 65535 байт.

Приклад директиви:

{$М 20000,10000,200000}

Перше число показує розмір сегмента стеку (від 1024 до 655356). Це число вибирається в за­лежності від наявності та виду підпрограм. Друге число визначає найменш допустимий в даній прог­рамі розмір Heap, а останнє число - найбільший розмір цієї пам'яті. Конкретні розміри Heap виби­раються в залежності від задачі та кількості дина­мічних даних.

Адреса задаются двумя 16-тиразрядными словами (тип word) - сегментом и смещением. Каждое из них способно адресовать 216=65536 байт (64 Кбайт). Для адресации пространства размером в 1 Мбайт требуется 20 разрядов. Сегменты адресуют память с точностью до параграфа - фрагмента памяти в 16 байт. Смещение адресует память с точностью до байта, но впределах сегмента. Реальный (абсолютный) адрес складывается из значения сегмента, сдвинутого на 4 разряда влево (умноженного на 16), и смещения. Фрагмент программы вычисления абсолютного адреса в реальном режиме:

Var Segment, Offset : word; Address : LongInt; . . . Address := Segment*16+Offset;

Программа на Паскале получает один сегмент данных, поэтому область памяти, в которой могут быть размещены статические переменные Вашей программы, ограничена 64 Кбайтами. При попытке исполнить программу, требующую большего размера памяти, будет выдана ошибка:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]