Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Модульність, розподіл пам'яті, підпрограми.doc
Скачиваний:
2
Добавлен:
25.11.2018
Размер:
764.42 Кб
Скачать

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

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

покажчик елемент даних

адреса

Формат задання адреси:

базис сегмента : зсув,

де базис сегмента – 16-ве число, що визначає адресу початку сегмента ОП (номер 16-байтового блоку, з якого починається сегмент; кратний 16);

зсув – 16-ве число, що визначає зміщення потрібного байта пам'яті відносно початку сегмента.

Наприклад, 000А:001А.

Такий спосіб запису адреси пов'язаний з тим, що в операційній системі DOS вся пам'ять розбита на сегменти, розміри яких не перевищують 64 Кбайт. Для отримання абсолютної адреси система додає до базису сегмента справа шістнадцятковий нуль (це чотири нулі в двійковій системі), а потім складає його зі зміщенням. Таким способом можна адресувати 1 Мбайт пам'яті.

Для зберігання значення покажчика (адреси) необхідно 4 байти ОП: 2 байти – для базису сегмента, 2 байти – для значення зсуву.

Синтаксис оголошення покажчиків різниться у різних мовах програмування. Так у Pascal покажчики оголошуються наступним чином:

^ базовий тип;

Тут знак “^” треба читати як “посилання на ...”.

Наприклад,

var p, ptr : ^real;

w : ^word;

Ініціалізація покажчиків здійснюється у Pascal, зазвичай, за допомогою операції отримання адреси @ або стандартної функції аddr. Наприклад,

var v: word;

p, w : ^word;

...

v := 5;

p := @v;

w := addr(v);

...

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

 Nil вказує на адресу оперативної пам'яті (0000:0000), за якою свідомо не може бути розміщена ніяка інформація.

Звертання до значення, на яке вказує покажчик, здійснюється через розіменування посилання по формату:

покажчик^.

Наприклад,

w ^ := 56;

writeln (‘Значення дорівнює ’, w ^);

Тут w^ означає елемент даних, на який посилається покажчик w:

w w ^

адреса  56

Таким чином, змінна посилається на значення прямо, а покажчик – опосередковано.

У мові С формат оголошення покажчиків має наступний вигляд:

базовий тип *покажчик;

Наприклад,

int *p, number;

float *ptr, *r;

 Кожен покажчик повинен бути оголошений своїм символом *.

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

int n;

int *nPtr = &n;

n = 7;

int n, *nPtr;

n = 7;

nPtr = &n;

Покажчик може отримати в якості початкового значення також пусте посилання null. Макрос null, що є константним нуль-покажчиком, визначений в заголовочних файлах stdlib.h, stddef.h та ін.

Звертання до відповідного значення здійснюється по формату:

*покажчик.

Наприклад,

int n, *p;

n = 7;

*p = 9;

cout << “n: “ << n << endl;

cout << “*p: “ << *p << endl;

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

Тому над покажчиками визначені лише операція присвоєння і деякі операції порівняння.

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

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

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

  • покажчик;

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

  • порожній покажчик (nil, null).

Розглянемо приклад на мові Pascal. Нехай у програмі описані наступні покажчики:

var p,w :^word;

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

p^ := 3;

w^ := 58;

p := w;

w := nil;

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

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

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

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

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

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

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

var p, w : ^word;

begin

...

if p=nil then w:= p;

...

end;

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

#include <iostream.h>

main( )

{ int n, *nPtr;

n = 7;

nPtr = &n;

cout<<“Адреса n:“<<&n<<endl<<“Значення nPtr:“<<nPtr<<endl;

cout<<“Значення n:“<<&n<<endl<<“Значення *nPtr:“<<*nPtr<<endl;

}

Посилання. Посилання – це псевдонім (інше ім’я) змінної. Для нього не резервується місце в ОП. Формат оголошення псевдоніма:

базовий тип &псевдонім.

Кожен псевдонім повинен бути оголошений своїм символом &.

Посилання повинно бути ініціалізоване при його оголошенні. Наприклад,

int n = 5;

int &p = n, x = 3, &y = x;

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