MІНІСТЕРСТВО ОСВІТИ УКРАЇНИ
Державний університет “Львівська політехніка”
ДИНАМІЧНЕ ВИДІЛЕННЯ ПАМ’ЯТІВ МОВІ ПРОГРАМУВАННЯ С
Інструкція
до лабораторної роботи N 6
з курсу “Проблемно-орієнтовані мови програмування”
для студентів базового напрямку 6.08.04
"Комп’ютерні науки"
ЗАТВЕРДЖЕНО
на засіданні кафедри
Системи автоматизованого проектування
Протокол N від р.
ЛЬВІВ 1998
Динамічне виділення пам’яті в мові програмування С. Інструкції до лабораторної роботи № 6 з курсу “Проблемно-орієнтовані мови програмування” для студентів базового напрямку 6.08.04 "Комп’ютерні науки“ /Укл. С.І. Бобало, О.Р. Корбецький -Львів: ДУ “ЛП”, 1998р. - с.
Укладачі С.І. Бобало, асист.,
О.Р. Корбецький, асп.
Відповідальний за випуск С.П. Ткаченко, канд.техн.наук, доц.
Рецензенти В.І.Каркульовський, канд.техн.наук,
І.І.Чура, канд.техн.наук
1. МЕТА РОБОТИ
Мета роботи - ознайомитися з особливостями застосування функцій виділення та звільнення пам’яті вмові програмування С та навчитися практично їх застосовувати
2. ТЕОРЕТИЧНІ ВІДОМОСТІ
Існує два основних шляхи за допомогою яких програма написана на С може зберігати інформацію в основній пам’яті комп’ютера.
Перший шлях використовує глобальні та локальні змінні, що визначені в С, яким виділено необхідну кількість байтів пам’яті самим компілятором, наприклад:
int x; виділено 2 бaйта
char s; виділено 1 бaйт
float f; виділено 4 бaйта
double d; виділено 8 бaйт
int y[10]; виділено 2x10 бaйт
Останній приклад заслуговує більшу увагу. Коли компілятор зустрічає вираз “тип_змінної ім’я_змінної [кількість], то він автоматично резервує потрібну кількість байтів на час виконання програми. До певного часу так зручно. Але розглянемо ситуацію, коли Вам необхідно зформувати одномірний масив з наперед невизначеним числом елементів. Звичайно Ви можете написати щось на зразок int y[100], у випадку коли кількість елементів рівна 100 ваша програма буде працювати ефективно. У випадку, коли кількість елементів буде менше 100, скажімо 2, то із 100*2 байта зарезервовані компілятором, (100-2)х2 байтів витрачені зайво. Ще гірше у випадку коли кількість елементів більше 100, тоді ваша програма буде працювати некоректно, якщо ви не передбачили такої ситуації. Що ж робити ?
Ідеальним рішенням такої поширеної проблеми є динамічне (тобто стільки скільки потрібно) виділення пам’яті. В описаній вище ситуації такий підхід дозволить максимально ефективно використати пам’ять. Якщо Ви бажаєте писати професійні програми на С, то володіння і використання динамічного виділення пам’яті є необхідним.
Виділення і звільнення пам’яті
Функції malloc() та free() є основні функції для роботи з пам’ятю в С. Функція malloc() виділяє пам’ять, а функція free() звільняє її. Це означає, що при кожному виклику malloc() виділяється порція вільної пам’яті. В свою чергу, при кожному виклику free() виділена пам’ять повертається в систему. Кожна програма, яка використовує ці функції повинна містити заголовочний файл stdlib.h в якому зберігаються прототипи цих функцій.
Прототип функції malloc():
void* malloc() (unsigned число_байт)
Він повертає вказівник типу void, який означає, що Ви можете призначити його до будь-якого типу вказівника. Після успішного виклику malloc() поверне вказівник до першого байта області пам’яті виділеного з “кучі”. В протилежному випадку функція поверне значення нуль. Ви можете використати функцію sizeof() для визначення точного числа байтів потрібного для кожного типу даних.
Прототип функції free():
void free(void*p);
Ви мусите пам’ятати тільки одну важливу річ - ніколи не викликати free() з неправильним аргументом, тому що це приведе до непередбачуваних дій комп’ютера.
Наступна коротка програма виділяє пам’ять для 60 цілих чисел, друкуючи їх значення і звільняючи пам’ять для подальшого використання:
#inсlude <stdio.h>
#inсlude <stdlib.h>
main (void)
{
int*p,t;
p=malloc(60*sizeof(int));
if(!p) /* чи достатньо пам’яті */
printf(“out of memory\n”);
else {
for (t=0; t<60; t++) *(p+t) = t;
for (t=0; t<60; t++) printf(“%d”, *(p+t));
free(p);
}
return 0;
}
Наступний приклад динамічного виділення дозволить вам відчути зручність такого підходу.
#inсlude <stdio.h>
#inсlude <stdlib.h>
main (void)
{
int i, num;
float *p, t;
float avg;
printf(“Введіть кількість цілих чисел : ” );
scanf(“%d”, &num);
/* виділення місця для одномірного масиву*/
if((p=malloc(sizeof(float)*num)) == NULL) {
printf(“allocation error”);
exit (1);
}
for(i=0; i<num; i++) {
printf(“%d: ”, i+1);
scanf(“%f”, &p[i]);
}
avg=0;
for(i=0; i<num; i++) avg = avg + p[i];
printf(“середнє: %f:”, avg/num);
free(p); /*звільнення*/
return 0;
}
Наступний більш складний приклад демонструє використання динамічного виділення пам’яті для двомірного масиву, який широко використовується в програмуванні
#inсlude <stdio.h>
#inсlude <stdlib.h>
main (void)
{
float **p; /*вказівник не вказівник*/
int i, j, maxI, maxJ;
printf(“Введіть кількість чисел по горизонталі : ”);
scanf(“%d”, &maxI);
printf(“Введіть кількість чисел по вертикалі : ”);
scanf(“%d”, &maxJ);
p=malloc(maxJ* sizeof(float*));
/*формується масив вказівників*/
if((p==NULL) {
printf(“allocation error”);
exit (1);
}
for(j=0; j < maxJ; j++)
for(i=0; I < maxI; i++) {
p[j] = malloc(maxI* sizeof(float));
if(p[j] == NULL) {
printf(“allocation error”);
exit (1);
}
}
…
/*будь-які дії з масивом, додавання, роздрук, тощо*/
…
/*звільнення пам’яті*/
for(j=0; j < maxJ; j++)
free p[j];
free(p);
return 0;
}
СПИСОК ЛІТЕРАТУРИ
Herbert Schildt Using Turbo C++ VcGfaw-Hill, 1990/
А.Н.Касаткин, А.Н.Вальвачев Профессиональное программирование на языке Си. ОTTurbo C++ Borland C++. -Минск. -1992.