мета-данные страницы
Загрузка не удалась. Возможно, проблемы с правами доступа?
Различия
Показаны различия между двумя версиями страницы.
Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
pascal:pointers [21/11/2009 18:12] – oca | pascal:pointers [21/11/2009 18:16] (текущий) – oca | ||
---|---|---|---|
Строка 2: | Строка 2: | ||
FIXME | FIXME | ||
+ | ===== Использование указателей в Паскале ===== | ||
+ | |||
+ | http:// | ||
+ | |||
+ | Подведем некоторые итоги. Итак, динамическая память составляет 200…300 Кбайт или больше, | ||
+ | |||
+ | Посмотрим, | ||
+ | |||
+ | Казалось бы, эту проблему можно решить следующим образом: | ||
+ | |||
+ | var | ||
+ | |||
+ | i,j : Integer; | ||
+ | |||
+ | PtrArr : array [1..100, 1...200] of Real; | ||
+ | |||
+ | begin | ||
+ | |||
+ | for i := 1 to 100 do | ||
+ | |||
+ | for j := 1 to 200 do | ||
+ | |||
+ | new(PtrArr[i, | ||
+ | |||
+ | ……. | ||
+ | |||
+ | end. | ||
+ | |||
+ | Теперь к любому элементу вновь созданного динамического массива можно обратиться по адресу, | ||
+ | |||
+ | PtrArr[1,1] := 0; | ||
+ | |||
+ | if PtrArr[i, | ||
+ | |||
+ | Вспомним, | ||
+ | |||
+ | Выходом из положения могла бы послужить адресная арифметика, | ||
+ | |||
+ | Тем не менее, решить указанную задачу все-таки можно. Как мы уже знаем, любой указатель состоит из двух слов типа WORD, в которых хранятся сегмент и смещение. В Турбо Паскале определены две встроенные функции типа WORD, позволяющие получить содержимое этих слов: | ||
+ | |||
+ | SEG(X) – возвращает сегментную часть адреса; | ||
+ | |||
+ | OFS(X) – возвращает смещение. | ||
+ | |||
+ | Аргументом X при обращении к этим функциям может служить любая переменная, | ||
+ | |||
+ | var | ||
+ | |||
+ | р : Real; | ||
+ | |||
+ | begin | ||
+ | |||
+ | …… | ||
+ | |||
+ | new(p); | ||
+ | |||
+ | р := 3.14; | ||
+ | |||
+ | ……. | ||
+ | |||
+ | end. | ||
+ | |||
+ | то функция SEG(P) вернет сегментную часть адреса, | ||
+ | |||
+ | С другой стороны, | ||
+ | |||
+ | PTR(SEG, | ||
+ | |||
+ | можно создать значение указателя, | ||
+ | |||
+ | var | ||
+ | |||
+ | i, | ||
+ | |||
+ | PtrStr : array [1..100] of pointer; | ||
+ | |||
+ | const | ||
+ | |||
+ | SizeOfReal = 6; | ||
+ | |||
+ | begin | ||
+ | |||
+ | for i := 1 to 100 do | ||
+ | |||
+ | GetMem (PtrStr [i] , SizeOfReal*200) ; | ||
+ | |||
+ | ……. | ||
+ | |||
+ | {Обращение к элементу матрицы [i,j]} | ||
+ | |||
+ | pr := ptr(seg(PtrStr[i]), | ||
+ | |||
+ | ofs(PtrStr[i])+(j-1)*SizeOfReal); | ||
+ | |||
+ | if рr > 1 then | ||
+ | |||
+ | ……. | ||
+ | |||
+ | end. | ||
+ | |||
+ | Поскольку оператор вычисления адреса PR := PTR… будет, судя по всему, использоваться в программе неоднократно, | ||
+ | |||
+ | Пример | ||
+ | |||
+ | const | ||
+ | |||
+ | SizeOfReal = 6; {Длина переменной типа REAL} | ||
+ | |||
+ | N = 100; {Количество столбцов} | ||
+ | |||
+ | М = 200; {Количество строк} | ||
+ | |||
+ | var | ||
+ | |||
+ | i,j : Integer; | ||
+ | |||
+ | PtrStr: array [1..N] of pointer;. | ||
+ | |||
+ | s : Real ; | ||
+ | |||
+ | type | ||
+ | |||
+ | RealPoint =^Real; | ||
+ | |||
+ | {——————-} | ||
+ | |||
+ | Function AddrR(i,j: word): RealPoint; | ||
+ | |||
+ | {По сегменту i и смещению j выдает адрес вещественной переменной} | ||
+ | |||
+ | begin | ||
+ | |||
+ | AddrR := ptr(seg (PtrStr [i]), | ||
+ | |||
+ | ofs{ PtrStr [i]) + (j -1) * SizeOfReal) | ||
+ | |||
+ | end {AddrR} ; | ||
+ | |||
+ | {——————-} | ||
+ | |||
+ | Function GetR(i,j: Integer): Real; | ||
+ | |||
+ | {Выдает значение вещественной переменной по сегменту i и смещению j ее адреса} | ||
+ | |||
+ | begin | ||
+ | |||
+ | GetR := AddrR(i,j) | ||
+ | |||
+ | end {GetR}; | ||
+ | |||
+ | {——————-} | ||
+ | |||
+ | Procepure PutR(i,j : Integer; x: Real); | ||
+ | |||
+ | {Помещает в переменную, | ||
+ | |||
+ | begin | ||
+ | |||
+ | AddrR ( i , j ) : = x | ||
+ | |||
+ | end {PutR}; | ||
+ | |||
+ | {——————-} | ||
+ | |||
+ | begin {Main} | ||
+ | |||
+ | for i :=1 to N do | ||
+ | |||
+ | begin | ||
+ | |||
+ | GetMem (PtrStr [i] , M*SizeOfReal) ; | ||
+ | |||
+ | for j := 1 to M do PutR(i, j, Random) | ||
+ | |||
+ | end; | ||
+ | |||
+ | S := 0; | ||
+ | |||
+ | for i := 1 to N do | ||
+ | |||
+ | for j := 1 to M do | ||
+ | |||
+ | s := s +GetR(i,j); | ||
+ | |||
+ | WriteLn(s/ | ||
+ | |||
+ | end {Main} . | ||
+ | |||
+ | В рассмотренном примере предполагается, | ||
===== Процедуры и функции для работы с динамической памятью ===== | ===== Процедуры и функции для работы с динамической памятью ===== | ||
Строка 74: | Строка 263: | ||
MAXAVAIL | MAXAVAIL | ||
+ | |||
+ | Результат имеет тип LONGINT. За один вызов процедуры NEW или GETMEM нельзя зарезервировать памяти больше, | ||
+ | |||
+ | Функция MEMAVAIL. | ||
+ | |||
+ | Возвращает размер в байтах общего свободного пространства кучи. Обращение: | ||
+ | |||
+ | MEMAVAIL | ||
+ | |||
+ | Результат имеет тип LONGINT. | ||
+ | |||
+ | Процедура NEW. | ||
+ | |||
+ | Резервирует фрагмент кучи для размещения переменной. Обращение: | ||
+ | |||
+ | NEW ( ТР ) | ||
+ | |||
+ | Здесь ТР – типизированный указатель. | ||
+ | |||
+ | За одно обращение к процедуре можно зарезервировать не более 65521 байта динамической памяти. Если нет свободной памяти требуемого размера, | ||
+ | |||
+ | Процедура NEW может вызываться как функция. В этом случае параметром обращения к ней является тип переменной, | ||
+ | |||
+ | type | ||
+ | |||
+ | PInt =^Integer; | ||
+ | |||
+ | var | ||
+ | |||
+ | p: Pint; | ||
+ | |||
+ | begin | ||
+ | |||
+ | p := New(PInt); | ||
+ | |||
+ | …… | ||
+ | |||
+ | end. | ||
+ | |||
+ | При размещении в динамической памяти объекта разрешается в качестве второго параметра обращения к NEW указывать имя конструктора (см. гл.10). | ||
+ | |||
+ | Функция OFS. | ||
+ | |||
+ | Возвращает значение типа WORD, содержащее смещение адреса указанного объекта. Вызов: | ||
+ | |||
+ | OFS ( X ) | ||
+ | |||
+ | Здесь Х- выражение любого типа или имя процедуры. | ||
+ | |||
+ | Функция PTR. | ||
+ | |||
+ | Возвращает значение типа POINTER по заданному сегменту SEG и смещению OFS. Вызов: | ||
+ | |||
+ | PTR ( SEG, OFS ) | ||
+ | |||
+ | Здесь SEG – выражение типа WORD, содержащее сегмент; | ||
+ | |||
+ | OFS – выражение типа WORD, содержащее смещение. | ||
+ | |||
+ | Значение, | ||
+ | |||
+ | Процедура RELEASE. | ||
+ | |||
+ | Освобождает участок кучи. Обращение: | ||
+ | |||
+ | RELEASE ( PTR ) | ||
+ | |||
+ | Здесь PTR – указатель любого типа, в котором предварительно было сохранено процедурой MARK значение указателя кучи. Освобождается участок кучи от адреса, | ||
+ | |||
+ | Функция SEG. | ||
+ | |||
+ | Возвращает значение типа WORD, содержащее сегмент адреса указанного объекта. Вызов: | ||
+ | |||
+ | SEG ( X ) | ||
+ | |||
+ | Здесь X – выражение любого типа или имя процедуры. | ||
+ | |||
+ | Функция SIZEOF. | ||
+ | |||
+ | Возвращает длину в байтах внутреннего представления указанного объекта. Вызов: | ||
+ | |||
+ | SIZEOF ( X ) | ||
+ | |||
+ | Здесь X – имя переменной, |