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.