11.6. Ссылки, работающие не с кучей
Традиционно понятие «ссылка» всегда увязывается с динамическими переменными, кучей и т.п. У Турбо Паскаля тоже есть традиции. Одна из них — расширение общепринятых стандартов. В частности, ничто, кроме традиционных учебников стандартного Паскаля, не обязывает связывать ссылки или указатели именно с кучей. Ссылки могут указывать на что угодно: даже на выполнимый код программы (крайний и бесполезный случай). Обычно в разных трюках ссылки связываются со статическими данными или с системными областями памяти ПЭВМ (областью данных БСВВ, видеопамятью и др.).
Кроме способа связывания, такие ссылки ничем не отличаются от рассмотренных ранее (рис. 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! Динамические переменные здесь не создаются и не освобождаются. Взамен этого в ссылки «ручным способом» записываются адреса тех блоков памяти, с которыми мы хотели бы работать. А далее мы обращаемся с ними, как будто они есть структурированные динамические переменные.
Подобная техника открывает доступ к видеопамяти через любые структуры, позволяет проделывать такие вещи, как запись текстов с экрана на диск или их загрузку, подмену структур обращения к данным (как альтернатива приведению типов) и многое другое. Ссылки без кучи в последующих программах-иллюстрациях будут использоваться не раз, особенно при работе с видеопамятью.