МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
Національний університет “Львівська політехніка”
ДИНАМІЧНЕ ВИДІЛЕННЯ ПАМ’ЯТІВ МОВІ ПРОГРАМУВАННЯ С
Інструкція
до лабораторної роботи № 6
з курсу “Проблемно-орієнтовані мови програмування”
для студентів базового напрямку 6.08.04
"Комп’ютерні науки"
ЗАТВЕРДЖЕНО
на засіданні кафедри
Системи автоматизованого проектування
Протокол № від р.
ЛЬВІВ 2004
Динамічне виділення пам’яті в мові програмування С. Інструкція до лабораторної роботи № 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.
А.Н.Касаткин, А.Н.Вальвачев Профессиональное программирование на языке Си. От Turbo C++ к Borland C++. -Минск. -1992.