Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lab4.doc
Скачиваний:
6
Добавлен:
21.09.2019
Размер:
146.94 Кб
Скачать

Динамічне виділення і вказівники

У всіх відкомпільованих програмах С при розміщенні в пам’яті можна виділити 4 області: код програми, глобальні дані, стек і купа. Купа (heap) – це область вільної пам’яті, якою можна керувати через функції динамічного виділення malloc() і free(). Розглянемо ці функції детальніше.

Функція malloc() виділяє пам’ять і повертає вказівник на початок виділеного блоку. Функція free() повертає раніше виділену пам’ять в купу для повторного використання. Прототипи функцій malloc() і free():

void *malloc(size_t кількість­_байт); void free(void *p);

Обидві функції використовують заготовочний файл stdlib.h. Тут кількість_байт ­– це число потрібних байт. Якщо недостатньо вільної пам’яті для виконання запиту, malloc() повертає NULL. Тип size_t визначений в stdlib.h і є беззнаковим цілим типом, який здатний зберігати розмір пам’яті, що виділяється при одному виклику malloc(). Важливо те, що free() повинна викликатися тільки з коректним виділеним раніше вказівником, інакше структура купі може бути пошкоджена, що може привести до краху програми.

Фрагмент коду, показаний нижче, виділяє 25 байт пам’яті:

сhar *p; p = (char *) malloc(25);

Після присвоєння, p вказує на перший з 25 виділених байт. Оператор перетворення типу char* не потрібен в С, але потрібен в С++.

Оскільки купа не нескінченна, то при виділенні пам’яті необхідно перевіряти значення, яке повертається malloc(), щоб переконатися що воно не нульове. Використання нульового вказівника може привести до зависання комп’ютера. Ось як коректно можна виділити пам’ять і протестувати на коректність вказівника:

int *p;

if((p = (int *) malloc(100))==NULL) { printf("Out of memory.\n"); exit(1); }

Макровизначення NULL знаходиться в stdlib.h. Звичайно, можна використовувати інший обробник помилок, крім exit(), Основне, не використовувати вказівник p, якщо він нульовий.

Слід включати заголовочний файл stdlib.h на початок всіх файлів, які використовують функції malloc() і free(), оскільки саме в ньому знаходяться їх прототипи.

Вказівники на константи

Модифікатор const можна використовувати для захисту об’єкта від можливої його зміни функцією. Тобто, коли вказівник передається у функцію, функція може модифікувати оригінал змінної на яку вказує вказівник. Якщо вказівник визначений як const, то функція не зможе модифікувати об’єкт. Наприклад, функція sp_to_dash() в такій програмі виводить дефіс замість кожного пробілу в рядку, що передається. Тобто рядок “this is a test” буде надруковано як “this-is-a-test”. Використання const при оголошенні параметра гарантує, що код функції не може модифікувати об’єкт, на який вказує параметр.

#include <stdio.h>

void sp_to_dash(const char *str);

int main(void)

{

sp_to_dash("this is a test");

return 0;

}

void sp_to_dash(const char *str)

{

while (*str) {

if (*str == ‘ ‘) printf ("%c", ‘-‘);

else printf ("%c", *str);

str ++;

}

}

Якщо написати sp_to_dash() таким чином, щоб вона модифікувала рядок, то вона не буде компілюватися. Наприклад, якщо написати:

//це неправильно

void sp_to_dash(const char *str)

{

while (*str) {

if (*str == ‘ ‘) *str = ‘-‘; //неможливо виконати

printf ("%c", *str);

str ++;

}

}

то виникне помилка в процесі компіляції.

Багато функцій в стандартних бібліотеках використовують const при оголошенні своїх параметрів. Це гарантує цілісність об’єктів, на які вказують параметри.

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