
- •1 Основні відомості про вказівники
- •2. Вказівники та посилання
- •Void function_a (char*, int, short*);
- •Int *pi; /* вказівник-змінна на дані типу int */
- •3. Ініціалізація вказівника
- •4. Розіменування та присвоєння
- •5. Void-вказівник
- •6. Операція пересування вказівника
- •7. Використання вказівників з модифікатором const
- •8. Деактивації дії модифікатора
- •9. Подвійний вказівник
- •10. Вказівники і масиви
- •11. Доступ до ділянок динамічної пам'яті
- •12. Звільнення пам'яті
- •8. Операції з вказівниками
- •Int I, *pi; /* pi –змінна-вказівник */
- •13. Динамічні масиви
- •11. Посилання
- •Лабораторный практикум
- •Вопросы без ответов
- •3 Основні операції над вказівниками
- •4 Багаторівнева непряма адресація
- •5 Операції над вказівниками
- •Void main ()
- •Void main()
- •6 Проблеми, пов'язані з вказівниками
- •Int *х; /* змінній-покажчику 'х' виділена оп, але 'х' не містить значення адреси оп для змінної */
- •Int *х; /* х - ім'я покажчика, він одержав оп*/
- •Void main ()
- •9 Масиви
- •1.9.1 Основні поняття
- •Int а[5]; /* оголошення зовнішнього масиву */ main ()
- •9.2 Оголошення та звертання в одновимірних масивах
- •9.3 Оголошення та звертання до багатовимірних масивів
- •Int а[3][4]; /* а - вказівник-константа */
- •10 Масиви покажчиків
- •10.1 Робота з великими масивами
- •Void main()
- •Int *p[200], I, j; clrscr() ;
- •10.2 Вільні масиви та покажчики
- •11 Символьні рядки
- •11.1 Основні відомості про представлення рядків
- •11.2 Функції роботи з рядками
- •1. Функції введення рядків.
- •2. Функції виведення рядків.
- •14 Лекція №14
- •14.1 Вказівники Лекція № 2 - Вказівники та посилання
- •1.2.1. Вказівники
- •6. Вказівники і масиви
- •6.1. Вказівники і адреси
- •6.2. Вказівники і аргументи функцій
- •6.3. Вказівники і масиви
- •6.4. Адресна арифметика
- •6.5. Вказівники символів і функції
- •6.6. Вказівники – не цілі значення
- •6.7. Багатовимірні масиви
- •6.8. Масиви вказівників (вказівники на вказівники)
- •6.9. Ініціалізація масивів вказівників
- •6.10. Вказівники і багатовимірні масиви
- •6.11. Командний рядок аргументів
- •6.12. Вказівники на функції
- •Посібник для початківця про вказівники
- •6. Вказівники і структуровані програмні змінні
- •9. Вказівники типу far
- •10. Вказівники і динамічні змінні (керування пам'яттю)
- •9. Вказівники типу far
- •10. Вказівники і динамічні змінні (керування пам'яттю)
- •8. Вказівники і динамічні змінні (керування пам'яттю)
- •Void* operator new(size_t t)
- •Void operator delete(void* p)
- •Void main()
6. Вказівники і масиви
Цей розділ присвячено вказівникам і масивам та їх способам використання в прикладних програмах. Вказівник – це змінна, яка містить адресу іншої змінної. Вказівники широко використовують у мові C++, оскільки іноді вони дають єдину можливість виразити потрібну дію, і дозволяють розробляти компактні й ефективні програми.
6.1. Вказівники і адреси
Вказівник містить адресу об’єкта, що дає змогу «непрямого» доступу до цього об’єкта через вказівник. Якщо х – змінна типу int, рх – вказівник, а унарна операція & видає адресу об’єкта, то оператор рх = &х; присвоює адресу х змінній рх, тобто рх «вказує» на х. Операцію & застосовують тільки до змінних і елементів масиву, її також не можна застосовувати до регістрової змінної.
Унарна операція * розглядає свій операнд як адресу змінної і звертається за цією адресою, щоб одержати значення змінної. Отже, якщо змінна y типу int, то y = *рх; присвоює y значення того, на що вказує рх. Тому послідовність:
рх = &х;
y = *рх;
присвоює y те ж саме значення, що й оператор y = x;
Змінні потрібно описати:
int x, y; // опис x і y
int *px; // опис вказівника
Мнемонічний опис вказівника int *px; свідчить про те, що комбінація *px має тип int. Це означає, що якщо px з’являється в контексті *px, то це еквівалентно змінній типу int. Фактично синтаксис опису змінної імітує синтаксис виразів, у яких ця змінна може з’являтися. Наприклад, double Atof(), *dp; показує, що Atof() і *dp мають у виразах значення типу double. Зауважимо, що вказівник може вказувати тільки на певний вид об’єктів. Вказівники можуть входити у вираз. Наприклад, якщо px вказує на ціле x, то *px може з’являтися в будь-якому контексті, де може трапитися x. Так, оператор y = *px + 1 присвоює y значення на одиницю більше відзначення x; printf("%d\n", *px) – друкує поточне значення x; d = sqrt((double) *px) – отримує в d квадратний корінь із x, причому до передачі функції sqrt значення x перетворюється до типу double.
У виразах вигляду у = *px + 1 унарні операції * і & зв’язані зі своїм операндом, тому такий вираз бере те значення, на яке вказує px, додає одиницю і присвоює результат змінній y.
Посилання на вказівники можуть з’являтися і в лівій частині присвоєнь. Якщо px вказує на x, то *px = 0 встановлює x = 0, а *px += 1 збільшує його на одиницю, як і вираз (*px)++. Круглі дужки в (*px)++ необхідні. Якщо їх випустити (унарні операції типу *і++ виконуються справа наліво), то буде збільшено px, а не змінну, на яку він вказує.
Оскільки вказівники є змінними, то їх можна використовувати як звичайні змінні. Якщо py – інший вказівник на змінну типу int, то py = px копіює вміст px у py, в результаті чого py вказує на те ж, що й px.
6.2. Вказівники і аргументи функцій
У мові C++ передача аргументів функціям здійснюється «за значенням», тому викликана процедура не може безпосередньо змінити змінну із викличної програми. Наприклад, у програмі сортування (див. ПП6.1 на СD) потрібно поміняти два елементи за допомогою функції Swap. Для цього недостатньо написати Swap (a, b), через виклик за значенням swap не може впливати на аргументи a і b у викличній функції. Бажаний ефект можна одержати так. Виклична програма передає вказівники, які підлягають зміні значень: Swap(&a, &b); операція & видає адресу змінної, тому &a є вказівником на a. У swap аргументи описуються як вказівники і доступ до фактичних операндів здійснюється через них (див. ПП6.2 на СD).
Вказівники як аргументи використовуються у функціях, які повинні повертати більше одного значення. Наприклад, функція swap повертає два значення і нові значення її аргументів. Як приклад розглянемо функцію GetInt, що здійснює перетворення даних, які надходять у вільному форматі, розділяючи потік символів на цілі значення (по одному цілому за один цикл). Функція GetInt має повертати або знайдене значення, або ознаку EOF, якщо вхідні дані вичерпані. Ці значення повинні повертатися як окремі об’єкти, яке б значення не означало EOF.
У разі виходу на EOF GetInt повертає EOF як значення функції, а будь-яке інше повернуте значення – це нормальне ціле. Числове ж значення знайденого цілого повертається через аргумент, що має бути вказівником цілого. Такий підхід розділяє статус EOF і числові значення.
Наступний цикл заповнює масив цілими за допомогою звертань до функції GetInt:
int n, v, array[size];
for (n=0; n<size && GetInt(&v)!= eof; n++)
array[n]= v;
У результаті кожного обходу v стає рівним наступному цілому значенню, знайденому у вхідних даних. Як аргумент GetInt потрібно вказати &v, а не v. Використання просто v призведе до помилки адресації, оскільки GetInt працює з вказівником (див. ПП6.3 на СD).
Вираз *pn використовується в GetInt як звичайна змінна типу int. Задіяні функції GetCh та UngetCh, так, що один зайвий символ, який доводиться читати, може бути розміщений знову в потоці введення.