Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
07 Указатели.doc
Скачиваний:
5
Добавлен:
01.03.2025
Размер:
380 Кб
Скачать
☆

1.2.Операції з вказівниками

Над вказівниками можна виконувати ряд операцій:

  • присвоювання (=);

  • розіменування, або доступу за адресою (*);

  • перетворення типів;

  • отримання адреси (&);

  • підсумовування і віднімання (+ і –);

  • присвоювання після підсумовування і присвоювання після віднімання (+= і -=);

  • інкремент, або автозбільшення (++);

  • декремент, або автозменшення (––);

  • індексування ([]);

  • порівняння (==, !=, <, >, <=, >=);

  • динамічного розподілу пам’яті (new);

  • звільнення пам’яті (delete).

Розглянемо перелічені операції.

Присвоювання

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

int n, *p_int; long int *p_long; double d, *p_double; void *p_void; bool *p_bool;

помилковими будуть оператори

p_int = &d; p_long = p_int; p_double = p_void;

а оператори

p_int = &n; p_double = &d; p_void = p_int; p_int = NULL; p_int = (int *) &d; p_long = (long *) p_int; p_long = (long int *) p_int; p_double = (double *) p_void; p_bool = (bool *) p_void;

є правильними.

Розіменування

Операція розіменування записується в такому форматі:

(тип *) вираз

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

int *p = (int *)0xB8000000; int a = (int) p; // a == 134217728

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

int n = 10, *p; p = &n;

справедливим є співвідношення *p == 10.

Отримання адреси

Оскільки вказівник є деякою змінною, він має адресу, і цю адресу можна отримати, застосувавши до вказівника операцію &. Наприклад:

bool *p_bool; void *p_void = &p_bool;

Підсумовування і віднімання

  • Якщо два вказівника мають той самий тип, то до них застосовна операція віднімання, результатом виконання якої є «відстань» між ділянками пам’яті, на які вказують вказівники, в одиницях, кратних довжині базового типу вказівників (але не в байтах). Результат віднімання вказівників має тип unsigned long. При цьому різниця між двома числовими значеннями вказів­ників дорівнює кількості байт, на яку зміщені в пам’яті два вказівники відносно один до одного. Віднімання вказівників різного типу заборонене.

  • Для вказівників визначені операції віднімання цілого значення від вка­зівника і підсумовування вказівника і цілого значення. Результатом у такому разі є вказівник, зміщений на величину, що дорівнює вирахуваному (доданому) числу, помноженому на кількість байт, яку займає базовий тип.

Наприклад, нехай виконуються такі оператори:

double d; double *pd1, *pd2; int k; pd1 = &d; cin >> k; pd2 = pd1 + k;

У результаті вказівник pd2 буде вказувати на ділянку пам’яті, яка змі­щена відносно адреси змінної d на k * sizeof(double) байт. При цьому напрям зсуву залежитиме від знаку значення змінної k.

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

Наприклад, підсумовування елементів масиву можна забезпечити вико­нанням такого фрагменту програми:

int a[] = {2, 3, 4}, sum = 0; for (int *p = &a[0], i = 0; i < 3; i++, p++) sum += *p;

Але виконуватимуться і наступні два оператори for:

for (int *p = &a[0], i = 0; i >= -10; i--, p--) sum += *p; for (int *p = &a[0], i = 0; i < 30; i++, p++) sum += *p;

При цьому, якщо перший з трьох операторів for здійснює обробку тіль­ки елементів масиву, то інші два оператори for підсумовують ще й вміст комі­рок пам’яті, які в масив не входять.

  • Підсумовування вказівників заборонене.

  • Операції += і -= виконуються з урахуванням правил виконання операції присвоювання і операцій + та -.