мета-данные страницы
Загрузка не удалась. Возможно, проблемы с правами доступа?
Различия
Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слеваПредыдущая версия | |||
| 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} . | ||
| + | |||
| + | В рассмотренном примере предполагается, | ||
| ===== Процедуры и функции для работы с динамической памятью ===== | ===== Процедуры и функции для работы с динамической памятью ===== | ||