Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

1 (5)

.doc
Скачиваний:
21
Добавлен:
12.05.2015
Размер:
258.56 Кб
Скачать

ПЛАН

ПОКАЖЧИКИ ТА ПОСИЛАННЯ 1

Поняття покажчика 1

Дії над покажчиками 2

Посилання 4

ПОКАЖЧИКИ ТА ПОСИЛАННЯ

Поняття покажчика

Покажчики (вказівники) - це змінні, значеннями яких є адреси пам’яті. Найчастіше покажчики служать для зберігання інформації про місцезнаходження в пам'яті інших елементів даних (рис. 1). Наприклад, якщо змінна р містить адресу змінної n, то про змінну р говорять, що вона "вказує" на n.

Рис. 1. Зв'язок об’єкта з покажчиком, який вказує на цей об’єкт

Покажчики, так само як і будь-які інші елементи даних, розміщуються в пам'яті, займаючи в ній певну кількість байтів. Оскільки покажчик зберігає адресу іншого об'єкта, а адреса - це номер комірки пам'яті, то, незалежно від типу (а, отже, і розміру) об'єкта, на який вказує покажчик, сам об'єкт-покажчик завжди займає одну й ту ж кількість пам'яті (наприклад, у 32-розрядних операційних системах - 4 байти).

Покажчики мають бути відповідно оголошені. При цьому слід вказати тип даних, на які буде вказувати відповідний покажчик. У С/С++ формат оголошення покажчиків є таким:

тип* покажчик.

Символ "*" позначає покажчик і відноситься до типу змінної, тому його рекомендується ставить поряд з типом, а від імені змінної відділяти пробілом.

При одночасному оголошенні декількох покажчиків кожен із них повинен бути оголошений своїм символом "*". При цьому символ "*" ставиться перед іменем змінної-покажчика, оскільки інакше буде не зрозуміло, що ця змінна також є покажчиком.

Наприклад,

int* p;

float *ptr, *r; // два покажчика

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

int n;

int* nPtr = &n;

n = 7;

int n, *nPtr;

n = 7;

nPtr = &n;

Покажчик може отримати в якості початкового значення так зване пусте посилання (нуль-покажчик), яке не вказує ні на який об'єкт (вказує на адресу пам'яті, за якою не може бути розміщена ніяка інформація). Нуль-покажчик можна присвоювати покажчику на будь-який тип. Задається таке посилання, зазвичай, певною зарезервованою константою, наприклад, nil - у Pascal, NULL - у С/С++ (визначене в заголовочних файлах stdlib.h, stddef.h та ін.).

Звертання до значення, на яке вказує покажчик, здійснюється через операцію розіменування посилання. У різних мовах програмування ця операція має дещо різний формат. У С/С++ він має наступний вид:

*покажчик.

Наприклад,

int n, *p=&n;

n = 7;

*p = 9;

cout << “n=“ << n << endl; //виведеться n=9

Тут *p означає елемент даних, на який посилається покажчик p (рис. 2). При цьому змінна n посилається на значення прямо, а покажчик p – опосередковано (непрямо).

Рис. 2. Звертання до значення через операцію розіменування

Дії над покажчиками

Над покажчиками не визначені які-небудь операції, які б давали результат цього ж типу. І це зрозуміло — адже значеннями покажчиків є адреси тих або інших програмних об'єктів в пам'яті комп’ютера. А оскільки мова програмування високого рівня не містить яких-небудь правил щодо розміщення таких об'єктів в пам'яті комп’ютера (це питання вирішується самим транслятором), то неможливо сформулювати які-небудь розумні правила (операції), за допомогою яких в програмі можна було б визначити адресу одного об'єкту за адресами інших об'єктів. Тому над покажчиками визначені лише операція присвоєння і деякі операції порівняння.

Для присвоєння значення покажчику використовується оператор присвоєння наступного формату:

покажчик = посилальний_вираз,

де посилальний_вираз задає посилальне значення того ж типу, що і покажчик (посилається на програмні об'єкти того ж типу). При цьому як посилальний вираз може використовуватися:

  • покажчик;

  • функція, значенням якої є покажчик;

  • порожній покажчик (NULL).

Нехай у програмі описані наступні покажчики:

int n, m, *p=&n, *w=&m;

Прослідкуємо зміни їх значень і значень змінних, на які вказують ці покажчики, в результаті послідовного виконання наступних операторів присвоєння:

*p = 3;

*w = 58;

p = w;

w = NULL;

Для наочності отримані результати представимо у вигляді схеми (рис. 3).

Рис. 3. Зміна значень покажчиків при виконанні дій

Слід звернути увагу, що в даному прикладі після виконання оператора присвоєння р = w на об'єкт із значенням 3 не вказує жоден покажчик, тобто цей об'єкт став недоступним для програми. З іншого боку, в результаті виконання цього ж оператора присвоєння не утворюється новий об'єкт із значенням 58, а покажчик р починає вказувати на вже існуючий об'єкт (на який вказує і покажчик w).

Важливо чітко розуміти різницю між покажчиком і значенням об'єкту, на який посилається даний покажчик. Так, якщо замість оператора р = w у попередньому прикладі виконати оператор *р = *w, то отримаємо наступний результат (рис. 4):

Рис. 4. Приклад присвоєння значень елементам даних за допомогою покажчиків

Над покажчиками може бути визначено дві операції порівняння: "=" (дорівнює) і "≠" (не дорівнює). Оскільки машинні адреси по суті справи є цілими числами, то над покажчиками можна було б визначити і інші операції порівняння (<, , >, ), але у цьому немає необхідності, оскільки при формулюванні алгоритму нема сенсу використовувати інформацію про те, який з двох програмних об'єктів розташований ближче до початку (кінця) пам'яті, а який далі.

Два покажчика вважаються рівними, якщо вони обидва є порожніми посиланнями або вказують на один і той же об'єкт. У всіх інших випадках має місце нерівність покажчиків. Наприклад,

int n, m, *p=&n, *w=&m;

...

if (p=NULL) w= p;

У деяких мовах програмування, зокрема, у мовах С/С++ можна виводити адреси комірок пам’яті. Відповідні значення виводяться у 16-му вигляді. Наприклад,

int n, *nPtr = &n;

n = 7;

cout << "nPtr:" << nPtr << endl;

cout << "*nPtr:" << *nPtr << endl;

Відеокопія отриманого результату:

Посилання

Посилання – це синонім імені об'єкта, вказаного при ініціалізації посилання. Для посилання не резервується місце в пам'яті, воно є просто іншим ім'ям об'єкта.

Формат оголошення передбачає, що змінна-посилання повинна бути явно ініціалізована при її оголошенні:

тип &синонім= ім'я_об'єкта.

Наприклад,

int n = 5;

int &p = n;

Кожне посилання повинне бути оголошене своїм символом "&".

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

Наприклад,

int n = 7;

int &p = n;

cout << "n=" << р << endl; // виведеться n=7

Покажчики та посилання є однією із сильних сторін мов С/С++. Грамотне їх застосування дозволяє підвищити швидкість виконання програми і більш ефективно використовувати пам'ять. Наприклад, у багатьох випадках в якості аргументів функції краще використовувати покажчики на об'єкт, ніж щоразу створювати їхні копії.

Операция индексации может быть реализована с помощью адресной арифметики, где применяются операции ++,--, и +, -.

// пример применения указателей

cout<<"a= "<<a<<", "<<"b="<<b<<", c="<<c<< endl;

cout<<"*iptr = "<<*iptr<<endl;

cout<<"iptr[0] = "<<iptr[0]<<endl;

cout<<"iptr[1] = "<<iptr[1]<<endl;

cout<<"*(iptr + 1) = "<<*(iptr+1)<<endl;

cout<<"1[iptr] = " <<1[iptr]<<endl; // тоже возможный вариант

*iptr= 45; // меняем значение переменной a

cout<<"a = "<<a<<endl;

cout<<"----------------------------------------"<<endl;

// адресная арифметика

cout<<"iptr= "<<iptr<<endl; // вывод адреса в памяти переменной a

cout<<"iptr+1= "<<iptr+1<<endl; // вывод адреса в памяти переменной b

// разница между адресами переменных a и b в элементах

cout<<"delements=(iptr+1)-iptr = " << (iptr+1)-iptr <<endl;

// разница между адресами переменных a и b в байтах

cout<<"dbytes=(long)(iptr+1) - (long)iptr = " << (long)(iptr+1) - (long)iptr <<endl;

cout<<"dbytes=delements * sizeof(int) = "<< ((iptr+1)-iptr) * sizeof(int)<<endl;

cout<<"----------------------------------------"<<endl;

Как видно из этого примера, работа с указателями требует большой внимательности. Легко затереть не те данные, или обратиться по указателю к уже удаленному объекту или забыть удалить объект. Также указатели позволяют обойти некоторые ограничения языка (например обратиться к защищенному члену класса) и даже повлиять на систему в целом (например, в DOS программе зная адрес можно обратиться к системным переменным DOS или BIOS). Поэтому в некоторых языках как java полностью откзались от указателей ради безопасности.

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

5

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]