Програмування С, С++теорія та практика (частина 1)
1.8.6 Проблеми, пов’язані з покажчиками
Проблеми, пов‘язані з покажчиками, виникають при некоректному використанні покажчиків. Усі застереження щодо некоректного використання покажчиків відносяться до мови Сі так само, як і до багатьох інших низькорівневих мов програмування. Некоректним використанням покажчиків може бути:
• спроба працювати з неініціалізованим покажчиком, тобто з покажчиком, що не містить адреси ОП, що виділена змінній;
• втрата вказівника, тобто значення покажчика через присвоювання йому нового значення до звільнення ОП, яку він адресує;
• незвільнення ОП, що виділена за допомогою функції таІІос();
• спроба повернути як результат роботи функції адресу локальної змінної класу аиіо (про функції та класи змінних йтиметься далі);
Запит на виділення ОП з купи робиться за допомогою функцій саІІос() та таІІос(). Повернення (звільнення) ОП робиться за допомогою функції /гее(). Розглянемо деякі проблеми, пов'язані з покажчиками.
При оголошенні покажчика на скалярне значення будь-якого типу оперативна пам'ять для значення, що адресується, не резервується. Виділяється тільки ОП для змінної-покажчика, але покажчик при цьому не має значення. Якщо покажчик має специфікатор кіаііс, то ініціюється початкове значення покажчика, рівне нулю (особливості статичних змінних, про що йтиметься в окремому розділі). Приклад ініціалізації покажчиків нульовими значеннями при їх оголошенні: з-Ьа-Ьіс іп£ *рі, *рі; /* рі = НЛІіІі; рі= НПЬЬ; */
Розглянемо приклад, що містить грубу помилку: спробу працювати з непроініціалізованим покажчиком.
іп£ *х; /* змінній-покажчику 'х' виділена ОП, але 'х' не містить значення адреси ОП для змінної */ *х = 123; /* - груба помилка! */
Таке присвоювання помилкове, тому що змінна-покажчик х не має значення адреси, за яким має бути розташоване значення змінної. Компілятор видасть попередження:
Магпіпд: РоззіЬІе изе ої У Ьеіоге СеІіпШоп
При цьому випадкове (непроініціалізоване) значення покажчика (сміття) може бути неприпустимим адресним значенням! Наприклад, воно може збігатися з адресами розміщення програми або даних користувача, або даних операційної системи. Запис цілого числа 123 за такою адресою може порушити працездатність програми користувача або самої ОС. Компілятор не виявляє цю помилку, це повинен робити програміст!
Виправити ситуацію можна за допомогою функції таІІос(). Форма звертання до функції таІІос() наступна:
ім'я-покажчика = (тип-покажчика) таїїос ( об'єм -ОП ) ; де ім‘я-покажчика - ім'я змінної-покажчика, тип-покажчика - тип значення, що повертається функцією таїїос;
об‘єм-ОП - кількість байтів ОП, що виділяються змінній, яка адресується.
Наприклад:
х = (іп£ *) таїїос ( зігео£ (іп£) );
При цьому з купи виділяється 2 байти ОП для цілого значення, а отримана адреса його розміщення заноситься в змінну-покажчик х. Значення покажчика гарантовано не збігається з адресами, що використовуються іншими програмами, у тому числі програмами ОС. Параметр функції таїїос визначає об‘єм ОП для цілого значення за допомогою функції шво/(М). Запис (іпі *) означає, що адреса, що повертається функцією таїїос(), буде розглядатися як покажчик на змінну цілого типу. Це операція приведення типів.
Таким чином, помилки не буде у випадку використання наступних операторів:
іп£ *х; /* х - ім'я покажчика, він одержав ОП */
х = (іп£ *) таїїос ( зігео£(іп£));
/* Виділена ОП цілому значенню, на яке вказує 'х' */
*х = 123; /* змінна, на яку вказує 'х', одержала значення 123*/
Повернення (звільнення) ОП у купі виконує функція &ее(). Її аргументом є ім'я покажчика, що посилається на пам'ять, що звільняється. Наприклад:
£гее (х);
Щоб уникнути помилок при роботі з функціями не слід повертати як результат їхнього виконання адреси автоматичних (локальних) змінних функції. Оскільки при виході з функції пам'ять для всіх автоматичних змінних звільняється, повернута адреса може бути використаною системою й інформація за цією адресою може бути невірною. Можна повернути адресу ОП, що виділена з купи.
Одна з можливих помилок - подвійна вказівка на дані, розташовані у купі, і зменшення об‘єму доступної ОП через незвільнення отриманої ОП. Це може бути для будь-якого типу даних, у тому числі для скаляра або масиву. Розглянемо випадок для скаляра.
Приклад фрагмента програми з подвійною вказівкою і зменшенням об‘єму доступної ОП через незвільнення ОП наведений нижче:
#іпсїийе<а11ос.Ь>
Vоій. таіп ()
{
/* Виділення ОП динамічним змінним х, у и 2: */ іп£ *х = (іп£ *) таїїос ( зі2ео£(іп£)),
*у = (іп£ *) таїїос ( зі2ео£(іп£)),
*2 = (іп£ *) таїїос ( зі2ео£(іп£));
/* Ініціалізація значення покажчиків х, у, 2;*/
*х = 14; *у = 15; *2 = 17;
/*Динамічні змінні одержали конкретні цілі значення*/ у=х; /* груба помилка - втрата покажчика на динамічну змінну в без попереднього звільнення її ОП */
}
У наведеному вище прикладі немає оголошення імен змінних, є тільки покажчики на ці змінні. Після виконання оператора у = х; х та у є двома покажчиками на ту саму ОП змінної *х. Тобто *х = 14; і *у = 14. Крім того, 2 байти, виділені змінній, яку адресував у для розміщення цілого значення (*у), стають недоступними (загублені), тому що значення у, його адреса, замінені значенням х. А в купі ці 2 байти для *у вважаються зайнятими, тобто розмір купи зменшений на
2 байти. Відбулося зменшення доступної ОП. Цього слід уникати.
Щоб уникнути такої помилки треба попередньо звільнити ОП, виділену змінній *у, а потім виконати присвоювання значення змінній у. Наприклад:
£гее (у); /* звільнення ОП, виділеної змінної '*у' */
у = х; /* присвоювання нового значення змінній 'у' */
Чи можна змінній-покажчику присвоїти значення адреси в операторі оголошення ? Наприклад: іп£ *х = 12345;
Тут константа 12345 цілого типу, а значенням покажчика х може бути тільки адресою, покажчиком на байт в ОП. Тому компілятор при цьому видасть повідомлення про помилку:
Еггог РР.СРР 3: Саппої сопуегї ’іп! їо ’іп! *'
Проте не викличе помилки наступне присвоювання: іп£ а[5], *х = а;
Використання покажчиків часто пов'язано з використанням масивів різних типів. Кожний з типів даних масивів має свої особливості. Тому далі розглянемо властивості покажчиків для роботи
3 масивами.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
Схожі підручники
- Загальні питання з курсу Соціологія (частина 1)
- Фінансова діяльність суб'єктів підприємництва. Навчальний посібник (частина 1)
- Мікро економіка. План семінарських
- Соціальна педагогіка (частина 1)
- Скупой рыцарь (Сцены из ченстоновой трагикомедии The Covetous Knight) (онлайн)
- Бухгалтерський облік у галузях економіки (частина 1)
