Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

6.2.2. Важливість застосування базового типу покажчика

На прикладі попередньої програми було показано можливість присвоєння змінній value значення змінної balance за допомогою операції непрямого доступу, тобто з використанням покажчика. Можливо, при цьому у Вас промайнуло запитання: "Як С++-компілятор дізнається про те, скільки необхідно скопіювати байтів у змінну value з області пам'яті, яка адресується покажчиком ptr?". Сформулюємо те саме запитання в більш загальному вигляді: як С++-компілятор передає належну кількість байтів у процесі виконання операції присвоєння з використанням покажчика? Відповідь звучить так. Тип даних, який адресується покажчиком, вважається базовим типом покажчика. Оскільки ptr є покажчиком на цілочисельний тип, то у цьому випадку С++-компілятор скопіює в змінну value з області пам'яті, яка адресується покажчиком ptr, чотири байти інформації (що справедливе для 32-розрядного середовища). Але якби ми мали справу з double-покажчиком, то в аналогічній ситуації скопіювалося б вісім байтів інформації.

Змінні-покажчики повинні завжди вказувати на відповідний тип даних. Наприклад, під час оголошення покажчика типу int компілятор "припускає", що всі значення, на які посилається цей покажчик, мають тип int. С++-компілятор просто не дасть змоги виконати операцію присвоєння за участю покажчиків (з обох боків від оператора присвоєння), якщо типи цих покажчиків несумісні (по суті не однакові).

Наприклад, такий фрагмент коду програми є некоректним:

int *p;

double f;

//... р = &f; // Помилка!

Некоректність цього фрагмента полягає в неприпустимості присвоєння double-покажчика int-покажчику. Вираз &f генерує покажчик на double-значення, а р – покажчик на цілочисельний тип int. Ці два типи несумісні, тому компілятор відзначить цю настанову як помилкову і не скомпілює програму.

Як було заявлено вище, під час присвоєння два покажчики мають бути сумісні за типом, проте це серйозне обмеження можна подолати (правда, на свій страх і ризик) за допомогою операції приведення типів. Наприклад, такий фрагмент коду програми тепер формально є більш коректним:

int *p;

double f;

//...

p = (int *) &f; // Тепер формальне все ОК|!

Операція наведення до типу (int *) викличе перетворення double- до int-покажчика. Все ж таки використання операції приведення з цією метою є дещо сумнівним, оскільки саме базовий тип покажчика визначає, як компілятор поводитиметься з даними, на які він посилається. У цьому випадку, незважаючи на те, що р (після виконання останньої настанови) насправді вказує на значення з плинною крапкою, компілятор, як і раніше, "вважає", що він вказує на цілочисельне значення (оскільки р за визначенням – int-покажчик).

Щоб краще зрозуміти, чому використання операції приведення типів під час присвоєння одного покажчика іншому не завжди є допустимим, розглянемо таку програму.

Код програми 6.2. Демонстрація неправильного написання коду програми

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

int main()

{

double x, y;

int *p;

x = 123.23;

p = (int *) &x; // Використовуємо операцію приведення типів

// для присвоєння double-покажчика int-покажчику.

y = *p; // Що відбувається у процесі виконання цієї настанови?

cout << y; // Що виведе ця настанова?

getch(); return 0;

}

Як бачимо, у цій програмі змінній р (точніше, покажчику на цілочисельне значення) присвоюється адреса змінної х (яка має тип double). Отже, коли змінній y присвоюється значення, яка адресується покажчиком р, то змінна y отримує тільки чотири байти даних (а не всі вісім, що є потрібними для double-значення), оскільки р – покажчик на цілочисельний тип int. Таким чином, у процесі виконання cout-настанови на екран буде виведено не число 123.23, а, висловлюючись мовою програмістів, "сміття"1, яке насправді є молодшими 4-ма байтами мантиси.