Для доступу до даних за адресою Сі-програма використовує механізм покажчиків. Значення покажчика задає адресу об’єкту. Turbo C підтримує 4 модифікатора типу покажчика: near, far, huge, void. Модифікатори near, far та huge впливають на спосіб формування адреси.
Покажчик типу near задає неповну фізичну адресу, а лише зміщення (offset). Сегментна частина адреси визначається поточним значенням регістру DS. По замовчуванню всі покажчики в програмі є near-покажчиками для моделей пам’яті TINY, SMALL, COMPACT.
Покажчики типу far задають повну фізичну адресу об’єкту та при збереженні в пам’яті займають 4 байти. В пам’яті спочатку розміщується зміщення адреси (2 байти), потім сегмент адреси. Far-покажчик може ініціалізуватися при описі. В цьому разі записується значення і сегменту, і зміщення. Наприклад, для завдання початкового значення покажчика, що дорівнює адресі початку відеопам’яті кольорового адаптера, який працює у текстовому режимі (фізична адреса В8000h), необхідно вставити в Сі- текст такий опис:
char
far*vid_buf=0xb8000000; /*задає адресу B800:0000h*/
або після опису far-покажчика надати йому приведене значення. По замовчуванню всі покажчики в старших моделях пам’яті -MEDIUM, LARGE і HUGE- є far-покажчиками.
Покажчик типу huge аналогічний по змісту far-покажчику, але є так званим нормалізованим покажчиком.
На практиці часто виникає задача «збирання» far-покажчика із значень сегменту і зміщення, або його «розбирання» на сегмент і зміщення. Для рішення таких задач існує два способи. Перший полягає в використанні спеціальної структури, яка включається в об’єднання.
Наприклад:
struct point{
unsigned _off, _seg;
};
union P_MCB {
struct point p;
struct MCB far*mcb_ptr;
char far*far_char_ptr;
unsigned far* uns_far_ptr;
/* far- покажчики будь-які інші типи даних */
...
} work;
Шаблон структури point відповідає фізичному уявленню far-покажчика в пам’яті. Об’єднання змінної по шаблону point і far-покажчиків на різні типи дозволяє сформувати потрібне значення покажчика по відомим сегменту і зміщенню, або визначити по відомому значенню far-покажчика сегмент і зміщення. Одночасно вирішується проблема «перетворення» far-покажчиків на різні типи даних один в одного. Наприклад, одне і те ж значення покажчика може використовуватися для доступу до пам’яті через покажчик на структурну змінну по шаблону struct MCB, прочитати цю ж структурну змінну байт за байтом, використовуючи покажчик на тип char тощо. Припустимо, що необхідно прочитати перше слово (unsigned) префіксу сегменту програми, який розміщений на межі параграфу, що задається змінною _psp. Використовуючи описане раніше об’єднання work, зробити це можна так:
work.p._off = 0; /* задаємо нульове зміщення адреси */
work.p._seg =_psp; /* far- покажчик сформований */
first_word = *(work.uns_far_ptr); /* читаємо перше слово PSP */
Інший спосіб формування far-покажчика по відомим значенням сегменту та зміщення або, навпаки, визначення сегменту та зміщення far-покажчика полягає в використанні макро з файлу <dos.h>. Далі приводиться довідкова інформація про них:
#incclude < dos.h >
unsigned FP_OFF(void far*p)
unsigned FP_SEG(void far*p)
void far*MK_FP(unsigned seg,
unsigned ofs)
Макро FP_OFF() повертає
значення зміщення far-покажчика р, макро FP_SEG()-
значення сегменту far-покажчика р, макро MK_FP()-
значення far-покажчика, сформованого по заданим значенням сегменту seg та зміщення ofs. При використанні покажчика для доступу до
пам’яті необхідно виконувати наявне його перетворення до необхідного типу.
Наведемо приклади звернення до макро:
#include <dos.h>
...
unsigned my_offset, my_segment, key_stroke,
far *my_ptr = 0x0000041a;
my_offset = FP_OFF(my_ptr); /* надає значення, яке дорівнює 0x041а */
my_segment = FP_SEG (my_ptr); /*надає значення, яке дорівнює 0х0000 */
my_offset = *my_ptr; /*надає слово пам’яті за адресою 40:1Ah*/
/*Читання слова пам’яті 40:my_offset, що дорівнює коду клавіші. */
key_stroke = *(unsigned far*) MK_FP(0x40, my_offset);
...
Використання макровизначень приводить до більш довгого програмного коду, але є більш мобільним засобом.
![]() |
![]() |
![]() |