
- •Робота з вказівниками
- •Теоретичні відомості Масиви
- •Теоретичні відомості Вказівники Поняття про вказівники
- •Оператори для роботи з вказівниками.
- •Вирази з вказівниками
- •Присвоєння вказівників.
- •Арифметичні дії з вказівниками
- •Порівняння вказівників
- •Динамічне виділення і вказівники
- •Вказівники на константи
- •Вказівники і масиви
- •Вказівники на символьні масиви
- •Масиви вказівників
- •Вказівники на вказівники
- •Завдання
- •Вказівники
Теоретичні відомості Вказівники Поняття про вказівники
Вказівники – одна з найсильніших властивостей С/С++ з таких причин:
Вказівники надають можливість функціям модифікувати передані аргументи
Вказівники використовують для підтримання системи динамічного виділення пам’яті
Використання вказівників може підвищити ефективність роботи деяких підпрограм
Вказівники використовуються для підтримки таких структур даних як зв’язані списки і бінарні дерева
Вказівники – це адреси. Вказівник містить адресу комірки пам’яті. Як правило, це адреса розташування якоїсь змінної в пам’яті. Якщо одна змінна містить адресу іншої змінної, то говорять, що одна зміна вказує на іншу. Наприклад, якщо змінна за адресою 1000 вказує на змінну за адресою 1004, то за адресою 1000 буде знаходитися значення 1004. Ця ситуація зображена на рис.7.1.
Адреса комірки пам’яті |
Вміст комірки |
|
|
1004 |
|
q 1002 |
134 |
|
num 1004 |
255 |
Рис.7.1. Одна змінна вказує на іншу змінну
Змінна-вказівник.
Якщо змінна повинна містити вказівник, її оголошують таким чином: оголошення вказівника включає базовий тип, * та ім’я змінної. Стандартний вид оголошення вказівника такий:
тип* ім’я //один варіант; тип *ім’я //другий варіант.
Тип вказівника визначає тип змінної, на яку він вказує.
Оператори для роботи з вказівниками.
Є два спеціальних оператори для роботи з вказівниками – * та &. Розглянемо їх детальніше.
Оператор & – це унарний оператор, який повертає адресу операнда. Наприклад:
р = #
розмістить адресу змінної num в p. Ця адреса відповідає внутрішньому розміщенню змінної в комп’ютері. Вона нічого не робить зі значенням num. Операцію & можна розглядати як “отримання адреси”. Отже, попередній запис оператора присвоєння можна прочитати як “p отримує адресу num”.
Припустимо, що зміна num використовує адресу 1004 для зберігання в пам’яті свого значення (див. рис. 7.1). Також припустимо, що значення num – 255. В результаті цих припущень, р отримає значення 1004.
Оператор * доповнює оператор &. Оператор * – це унарний оператор, який повертає значення змінної, яка знаходиться за вказаною адресою. наприклад, якщо в p міститься адреса пам’яті змінної num, то
q = *р
розмістить значення num в q. Враховуючи наведені вище припущення, q отримає значення 255, оскільки 255 зберігається за адресою 1004. А 1004 є адресою, яка зберігається в р. Оператор * можна розглядати як “значення за адресою”. В даному випадку цей оператор можна прочитати як “q отримує значення за адресою p”.
Приклад програми, яка демонструє сказане вище:
#include <stdio.h>
int main(void)
{
int* p;
int q, num;
num = 255; //присвоєно 255 num
p = # //р отримує адресу num
q = *p; //q присвоюється 255 з використанням р
printf("%d", q);//виводить 255
return 0;
}
Працюючи з вказівниками, слід переконатися, що змінна-вказівник вказує на коректний тип даних. Наприклад, при оголошенні вказівника на тип int, компілятор припускає, що будь-яка адреса, яка міститься в змінній, вказує на цілочисельне значення. Оскільки С дозволяє присвоювати будь-яку адресу змінній-вказівнику, такий фрагмент коду компілюється (деякі з компіляторів видають помилку і не компілюють, деякі – видають попередження), але виконується з логічною помилкою:
#include <stdio.h>
int main(void)
{
double x, y;
int* p;
x = 100.123; //х присвоєно 100.123
p = &x; //р отримує адресу х — неправильно
y = *p; //у присвоюється 100.123 з використанням р
printf("%f", y); //неправильно
return 0;
}
Програма не присвоює значення x змінній y. Оскільки p оголошується як цілочисельний вказівник (припустимо, що в системі 16-бітне ціле), тільки 2 байти будуть перенесені до y, а не 8, як це за звичай робиться для double.