Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
РП_31_АСД.pdf
Скачиваний:
164
Добавлен:
23.02.2016
Размер:
2.92 Mб
Скачать

Тема 8. ФІЗИЧНА СТРУКТУРА ПОКАЖЧИКА

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

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

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

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

Фізичне представлення адреси істотно залежить від апаратної архітектури обчислювальної системи. Далі розглядається приклад структури адреси в мікропроцесорі i8086.

Машинне слово цього процесора має розмір 16 двійкових розрядів. Якщо використовувати представлення адреси в одному слові, то можна адресувати 64 Кбайт пам'яті, що явно недостатньо для скільки-небудь серйозного програмного виробу. Тому адреса представляється у вигляді двох 16-розрядних слів - сегмента і зсуву. Сегментна частина адреси завантажується в один із спеціальних сегментних регістрів (в i8086 таких регістрів 4). При зверненні за адресою задається ідентифікатор сегментного регістра і 16-бітове зсув. Повна фізична (ефективна) адреса утворюється таким чином. Сегментна частина адреси зсувається на 4 розряду вліво, звільнені зліва розряди заповнюються нулями, до отриманого таким чином коду додається зсув, як показано на рис. 1.

Отриманий ефективний адреса має розмір 20 двійкових розрядів, таким чином, він дозволяє адресувати до 1 Мбайт пам'яті.

зсув

повна

фізична

адреса

Рис. 1. Обчислення повної адреси в мікропроцесорі i8086.

27

Фізична структура адреси принципово різна для різних апаратних архітектур. Так, наприклад, в мікропроцесорі i386 обидва компоненти адреси 32-розрядні; в процесорах сімейства S/390 адреса представляється у вигляді 31-розрядного зсуву в одному з 19 адресних просторів, в процесорі Power PC 620 одним 64-розрядним словом може адресуватися вся як оперативна, так і зовнішня пам'ять.

Операційна система MS DOS була розроблена саме для процесора i8086 і використовує описану структуру адреси навіть тоді, коли виконується на більш досконалих процесорах. Однак, це сьогодні єдина операційна система, в середовищі якої програміст може працювати з адресами в реальній пам'яті і з фізичною структурою адреси. Всі без винятку сучасні моделі процесорів апаратно виконують так звану динамічну трансляцію адрес і спільно з сучасними операційними системами забезпечують роботу програм у віртуальній (уявній) пам'яті. Програма розробляється і виконується в деякій віртуальної пам'яті, адреси в якій лінійно змінюються від 0 до деякого максимального значення. Віртуальний адреса являє собою число - номер комірки в віртуальному адресному просторі. Перетворення віртуальної адреси в реальну проводиться апаратно при кожному зверненні за віртуальною адресою. Це перетворення виконується абсолютно непомітно (прозоро) для програміста, тому в сучасних системах програміст може вважати фізичною структурою адреси структуру віртуального адреси. Віртуальна ж адреса являє собою ціле число без знаку. У різних обчислювальних системах може відрізнятися розрядність цього числа. Більшість сучасних систем забезпечують 32-розрядну адресу, що дозволяє адресувати до 4 Гбайт пам'яті, але вже існують системи з 48 і навіть 64-розрядними адресами.

28

Тема 9. ПРЕДСТАВЛЕННЯ ПОКАЖЧИКІВ У МОВАХ ПРОГРАМУВАННЯ

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

var ipt: ^ integer; cpt: ^ char; або в мові C:

int * ipt; char * cpt;

означають, що змінна ipt являє собою адресу області пам'яті, в якій зберігається ціле число, а cpt - адреса області пам'яті, в якій зберігається символ. Хоча фізична структура адреси не залежить від типу і значення даних, що зберігаються за цією адресою, компілятор вважає, що покажчики ipt і cpt мають різний тип, і в Pascal оператор:

cpt: = ipt;

буде розцінений компілятором як помилковий (компілятор C для аналогічного оператора присвоювання обмежиться попередженням). Таким чином, коли мова йде про типізовані покажчики, правильніше говорити не про єдиний тип даних "покажчик", а про цілу родину типів: "покажчик на ціле", "покажчик на символ" і т.д. Можуть бути покажчики і на більш складні, інтегровані структури даних, і покажчики на покажчики.

Нетипізований покажчик - тип pointer в Pascal або void* в C - служить для представлення адреси, за якою містяться дані невідомого типу. Робота з нетипізований покажчиками істотно обмежена, вони можуть використовуватися тільки для збереження адреси, звернення за адресою, що задається нетипізовані покажчиком, неможливо.

Основними операціями, в яких беруть участь покажчики є присвоювання, отримання адреси, вибірка.

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

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

Операція вибірки - унарна, її операндом є типізований (обов'язково!) покажчик, результат - дані, вибрані з пам'яті за адресою, заданою операндом. Тип результату визначається типом покажчика-операнда.

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

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

29

Можна відняти один покажчик з іншого (обидва покажчики-операнди при цьому повинні мати однаковий тип). Результат такого обчислення матиме тип цілого числа зі знаком. Його значення показує на скільки байт (або інших одиниць виміру) одна адреса відстоїть від іншої в пам'яті.

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

Операції адресної арифметики виконуються тільки над типізований покажчиками. Одиницею виміру в адресній арифметиці є розмір об'єкта, який адресується покажчиком. Так, якщо змінна ipt визначена як покажчик на ціле число (int * ipt), то вираз ipt +1 дасть адресу, більший не на 1, а на кількість байт в цілому числі (в MS DOS - 2). Віднімання покажчиків також дає в результаті не кількість байт, а кількість об'єктів даного типу, що поміститься у пам'яті між двома адресами. Це справедливо як для покажчиків на прості типи, так і для покажчиків на складні об'єкти, розміри яких становлять десятки, сотні і більше байт.

У зв'язку з наявними в мові C розширеними засобами роботи з покажчиками, слід згадати і про різні представлення покажчиків у цій мові. В C покажчики будь-якого типу можуть бути ближніми (near) і дальніми (far) або (huge). Ця диференціація пов'язана з фізичною структурою адреси в i8086, яка була розглянута вище. Ближні покажчики являють собою зміщення в поточному сегменті Для подання такого покажчика достатньо одного 16-розрядного слова. Дальні покажчики представляються двома 16-розрядними словами - сегментом і зміщенням. Різниця між far або huge покажчиками полягає в тому, що для перших адресна арифметика працює тільки зі зміщенням, не зачіпаючи сегментну частину адреси, таким чином, операції адресної арифметики можуть змінювати адресу в діапазоні не більше 64 Кбайт; для других - в адресній арифметиці бере участь і сегментна частина, таким чином, межа зміни адреси - 1 Мбайт.

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

30