Урок #9

Робота з посиланнями і покажчиками

На цьому уроці піде мова про досить цікавою і одночасно складну тему. Тема начебто невелика, проте вимагає повного її розуміння.

Ми вже вміємо працювати зі звичайними змінними і навіть не замислюємося про те як вони працюють. На перший погляд може здатися, що це складно, але це не так. Давайте по черзі розглянемо процес оголошення змінної і присвоєння їй значения: short int number = 1. В даному випадку створюється змінна number типу short int. Але що означає саме ім’я цієї змінної? Воно являє собою якусь посилання на комірку пам’яті. Тобто вказує на клітинку з певним номером. Тип змінної визначає розмір пам’яті, яка буде виділятися для неї самої. Наприклад наша змінна number має двухбайтное тип short int і це значить, що в пам’яті буде виділено рівно два байта пам’яті, тобто 16 біт. Далі йде привласнення змінній значення 1: в осередок пам’яті, на яку посилається змінна number записується число 1.

Ось ми і розібралися з самим механізмом роботи зі змінними в програмі.

Робота з посиланнями

Посилання використовуються здебільшого тільки в двох випадках: при створенні копії змінної, або при передачі змінної в функцію і подальшої зміни її значення в функції. Для того, що б створити змінну-копію, необхідно перед її ім’ям написати знак & при її оголошенні:

256
Для продовження натисніть будь-яку клавішу…

Важливим є те, що при оголошенні такої копії обов’язково відразу писати якусь змінну вона буде копіювати, інакше код не скомпілюється.

Використання посилань у функціях

Поставимо перед собою просту задачу: збільшити значення змінної з використанням функції. Відповідь очевидна: створюємо функцію mult10 і в її тілі змінюємо значення змінної. Здавалося б, що це все. Але це не так. У цьому випадку змінна зміниться лише у функції, а в main залишиться колишньою. Рішенням даної задачі буде наступна програма:

160
Для продовження натисніть будь-яку клавішу…

Ця програма працює відмінно, змінна змінює своє значення, але вам не здається, що рядок number = mult10 (number) занадто довга? Особисто мені здається і зараз я покажу як її можна зменшити до елегантного mult10(number). Це робиться досить легко і відповідь досить прозора після вивчення першої частини цього уроку: зробити n в функції копією. Тоді функція, написана з копією буде виглядати так:

160
Для продовження натисніть будь-яку клавішу…

Як бачите, ми вбили відразу двох зайців: прибрали return в функції і скоротили рядок зі зміною змінної.

Покажчики

У цьому уроці ми досить багато говорили про те, що змінна вказує на певну комірку пам’яті. Але яку адресу саме має ця група? Для цього скористаємося покажчиками. Покажчики – змінні, які містять адресу, водночас з тим, як звичайна змінна містить те, що записано в цьому елементі пам’яті. Переконаємося в цьому, розглянувши наступний приклад:

256 00AFFEDC
256 00AFFEDC
Для продовження натисніть будь-яку клавішу…

Якщо ви запустите програму, ваш результат буде відрізнятися від того, який є на сайті, тому що програма буде шукати відповідну порожню область пам’яті, а вона майже ніколи не може бути такою ж, як і на іншому комп’ютері. Навіть на вашому комп’ютері при багаторазовому запуску цієї програми адреси завжди будуть інші, тому що в різний час в пам’яті вільні різні осередки. Але ці дві адреси будуть завжди однаковими, тому що змінна b є посиланням на клітинку, в якій міститься значення змінної a. Зверніть увагу на те як ми створюємо змінну-покажчик. Ми їй присвоюємо змінну, на яку хочемо посилатися, тільки перед її ім’ям пишемо знак &. Він так само використовується як оператор взяття адреси.

Арифметика покажчиків

Дивно, але покажчики можна додавати і віднімати. Але не між собою, а з будь-яким цілочисельним типом. Ви можете запитати: “А навіщо це?”. Відповідь проста: так працюють масиви. І справді, ім’я масиву слугує дороговказом на нульовий елемент, а для доступу до інших його елементів треба користуватися арифметикою покажчиків. Наприклад, у нас є масив arr, що складається з 5-ти елементів і ініціалізований так: int arr[] {1, 2, 4, 8, 16}. Тоді при виведенні лише імені масиву ми виведемо адресу першого елемента: cout << arr.

Тепер настав час усвідомити всю міць символу зірочки *. Даний символ служить не тільки для оголошення покажчиків, а й як оператор разіменовиванія посилання. Тобто якщо написати перед покажчиком цей оператор (ні до оголошенні покажчика), то ми будемо мати справу з даними, які зберігаються в цьому осередку пам'яті.

Як було сказано раніше, масиви повністю працюють на посиланнях, а назва масиву - покажчик на його нульовий елемент. Що б отримати значення цього нульового елемента, скористаємося оператором *. cout << *arr виведе число 1. Що б отримати доступ до інших елементів масиву, будемо додавати порядковий номер потрібного нам елементу масиву. Тобто для доступу до п'ятого елементу масиву необхідно написати *(arr + 4). Звичайно, можна скористатися і звичайним способом з квадратними дужками, але з покажчиками є кілька цікавих моментів, на які ми зараз і звернемо увагу.

Пропоную вам вивести адреси перших трьох елементів масиву. Це можна зробити за допомогою такої команди: cout << arr << endl << arr + 1 << endl << arr + 2 << endl. Ви можете подумати, що ці значення повинні відрізнятися лише на одиницю. Але ні, вони відрізняються аж на 4. Чому це сталося саме так? Справа в тому, що int є чотирьохбайтовим типом, тому для його зберігання в пам'яті потрібно цілих 4 байта. Цілком логічно, що додаючи номер елемента масиву, ми переходимо на 4 біта, а не на 1, бо якщо перейти лише на 1 байт, ми отримаємо якесь сміття, замість потрібного нам результату.

Можливі питання за темою:

Питань ще нема

Додавайте свої питання в коментарі. Кращі потраплять до статті 🙂


Урок #8 Урок #10