11.6. Ссылки, работающие не с кучей

We use cookies. Read the Privacy and Cookie Policy

Традиционно понятие «ссылка» всегда увязывается с динамическими переменными, кучей и т.п. У Турбо Паскаля тоже есть традиции. Одна из них — расширение общепринятых стандартов. В частности, ничто, кроме традиционных учебников стандартного Паскаля, не обязывает связывать ссылки или указатели именно с кучей. Ссылки могут указывать на что угодно: даже на выполнимый код программы (крайний и бесполезный случай). Обычно в разных трюках ссылки связываются со статическими данными или с системными областями памяти ПЭВМ (областью данных БСВВ, видеопамятью и др.).

Кроме способа связывания, такие ссылки ничем не отличаются от рассмотренных ранее (рис. 11.8).

| PROGRAM NoHeap;

| { ПРИМЕР ССЫЛОК БЕЗ ИСПОЛЬЗОВАНИЯ КУЧИ }

| TYPE { базовые типы: }

| VideoArray=Array[1..4000] of RECORD {структура экрана }

| Symbol : Char;

| Attrib : Byte

| END;

| Vector=Array[1..100] of Real; { одномерный массив }

| Matrix=Array[1..10,1..10] of Real;{ матрица 10 на 10 }

| VAR

| VideoPtr : ^VideoArray; { ссылка на структуру экрана }

| Vec : Vector; { ссылка на одномерный массив }

| MatPtr : ^Matrix; { ссылка на массив — матрицу }

| P : Pointer; { просто указатель }

| i : Word; { счетчик для циклов }

Рис. 11.8

- 212 -

| BEGIN

| VideoPtr := Ptr( $B800, 0 );

{Переменная VideoPtr теперь содержит адрес начала видеопамяти в цветных и черно-белых режимах. Для режима mono надо подставить в присваивании Ptr{$B000,0). После этого можно непосредственно обращаться к видеопамяти. }

| for i:=1 to 4000 do begin

| { Заполнение видеопамяти}

| VideoPtr^[i].Symbol:= '+'; { символом '+' в ярко- }

| VideoPtr^[i].Attrib:=15+128 { белом цвете с мерцанием}

| end {for};

| ReadLn; { пауза до нажатия клавиши ввода }

| { Заполнение статического массива Vec: }

| for i:=1 to 100 do Vec[i] := i*3.14;

| MatPtr := Addr(Vec); {передача его адреса ссылке MatPtr}

{Теперь к 100 элементам одномерного массива Vec можно обращаться и как к элементам матрицы 10x10, используя разыменование ссылочной переменной MatrPtr^. Здесь мы распечатаем диагональные элементы матрицы: }

| for i:=1 to 10 do WriteLn(' ':i, MatPtr^[i,i]:-9:2 );

| ReadLn; { пауза до нажатия клавиши ввода }

| { и т.п. }

| END.

Рис. 11.8 (окончание)

Советуем внимательно рассмотреть пример на рис. 11.8. В нем нет ни процедур New/Dispose, ни GetMem/FreeMem! Динамические переменные здесь не создаются и не освобождаются. Взамен этого в ссылки «ручным способом» записываются адреса тех блоков памяти, с которыми мы хотели бы работать. А далее мы обращаемся с ними, как будто они есть структурированные динамические переменные.

Подобная техника открывает доступ к видеопамяти через любые структуры, позволяет проделывать такие вещи, как запись текстов с экрана на диск или их загрузку, подмену структур обращения к данным (как альтернатива приведению типов) и многое другое. Ссылки без кучи в последующих программах-иллюстрациях будут использоваться не раз, особенно при работе с видеопамятью.