Автор: Пользователь скрыл имя, 18 Января 2012 в 14:01, курсовая работа
Цель курсовой работы является изучение указателя и динамической памяти в Турбо Паскаль.
Для достижения поставленной цели необходимо решить следующие задачи:
- изучить понятия указателей и динамической памяти.
- рассмотреть процедуры и функции с использованием указателей.
- рассмотреть применение указателей и работы с динамической памятью.
- привести пример программы, использующей динамическую память.
ВВЕДЕНИЕ 3
1. ПОНЯТИЕ УКАЗАТЕЛЕЙ И ДИНАМИЧЕСКОЙ ПАМЯТИ. 5
1.1 ПОНЯТИЕ ДИНАМИЧЕСКОЙ ПАМЯТИ. 5
1.2 АДРЕСА И УКАЗАТЕЛИ. 6
1.3 ОБЪЯВЛЕНИЕ УКАЗАТЕЛЕЙ. 7
2. ВЫДЕЛЕНИЕ И ОСВОБОЖДЕНИЕ ДИНАМИЧЕСКОЙ ПАМЯТИ. 9
2.1 ИСПОЛЬЗОВАНИЕ УКАЗАТЕЛЕЙ. 13
2.2. ПРОЦЕДУРЫ И ФУНКЦИИ ДЛЯ РАБОТЫ С ДИНАМИЧЕСКОЙ ПАМЯТЬЮ. 16
2.3 АДМИНИСТРАТОР КУЧИ. 19
3. КОНТРОЛЬ ЗА ДИНАМИЧЕСКОЙ ПАМЯТЬЮ. 21
4. ПРИМЕР ПРОГРАММЫ С УКАЗАТЕЛЕМ И ДИНАМИЧЕСКОЙ ПАМЯТЬЮ. 23
ЗАКЛЮЧЕНИЕ 26
var
i,j:Integer;
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)*
if рr > 1 then
.......
end.
Поскольку оператор вычисления адреса PR := PTR... будет, судя по всему, использоваться в программе неоднократно, полезно ввести вспомогательную функцию GETR, возвращающую значение элемента матрицы, и процедуру PUTR, устанавливающую новое значение элемента. Каждая из них, в свою очередь, обращается к функции ADDRR для вычисления адреса. В примере 1 приводится программа, создающая в памяти матрицу из NxM случайных чисел и вычисляющая их среднее значение.
Пример 1
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;
{Выдает
значение вещественной
begin
GetR := AddrR(i,j)
end {GetR};
{-------------------}
Procepure PutR(i,j : Integer; x: Real);
{Помещает в переменную, адрес которой имеет сегмент i и смещение j, вещественное значение x}
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/(N * М) :12:10)
end {Main} .
В
рассмотренном примере
Ниже приводится описание как уже рассмотренных процедур и функций, так и некоторых других, которые могут оказаться полезными при обращении к динамической памяти.
Функция ADDR - возвращает результат типа POINTER, в котором содержится адрес аргумента. Обращение:
ADDR ( X )
Здесь Х- любой объект программы (имя любой переменной, процедуры, функции). Возвращаемый адрес совместим с указателем любого типа.
Функция CSEG - возвращает значение, хранящееся в регистре CS микропроцессора в начале работы программы в регистре CS содержится сегмент начала кода программы. Обращение:
CSEG
Результат возвращается в слове типа WORD.
Процедура DISPOSE - возвращает в кучу фрагмент динамической памяти, который ранее был зарезервирован за типизированным указателем. Обращение:
DISPOSE(TP)
Здесь
ТР - типизированный указатель. При
повторном использовании
Функция DSEG - возвращает значение, хранящееся в регистре DS микропроцессора (в начале работы программы в регистре DS содержится сегмент начала данных программы). Обращение:
DSEG
Результат возвращается в слове типа WORD.
Процедура FREEMEM - возвращает в кучу фрагмент динамической памяти, который ранее был зарезервирован за нетипизированным указателем. Обращение:
FREEMEM ( Р, SIZE )
Здесь Р - нетипизированный указатель;
SIZE - длина в байтах освобождаемого фрагмента.
При повторном использовании процедуры применительно к уже освобожденному фрагменту возникает ошибка периода исполнения.
Процедура GETMEM - резервирует за нетипизированным указателем фрагмент динамической памяти требуемого размера. Обращение:
GETMEM ( Р, SIZE )
За одно обращение к процедуре можно зарезервировать не более 65521 байтов динамической памяти. Если нет свободной памяти требуемого размера, возникает ошибка периода исполнения. Если память не фрагментирована, последовательные обращения к процедуре будут резервировать последовательные участки памяти, так что начало следующего будет располагаться сразу за концом предыдущего.
Процедура MARK - запоминает текущее значение указателя кучи HEAPPTR. Обращение:
MARK ( PTR )
Здесь PTR - указатель любого типа, в котором будет возвращено текущее значение HEAPPTR. Используется совместно с процедурой RELEASE для освобождения части кучи.
Функция MAXAVAIL - возвращает размер в байтах наибольшего непрерывного участка кучи. Обращение:
MAXAVAIL
Результат имеет тип LONGINT. За один вызов процедуры NEW или GETMEM нельзя зарезервировать памяти больше, чем значение, возвращаемое этой функцией.
Функция MEMAVAIL - возвращает размер в байтах общего свободного пространства кучи. Обращение:
MEMAVAIL
Результат имеет тип LONGINT.
Процедура NEW - резервирует фрагмент кучи для размещения переменной. Обращение:
NEW ( ТР )
Здесь ТР - типизированный указатель.
За одно обращение к процедуре можно зарезервировать не более 65521 байта динамической памяти. Если нет свободной памяти требуемого размера, возникает ошибка периода исполнения. Если память не фрагментирована, последовательные обращения к процедуре будут резервировать последовательные участки памяти, так что начало следующего будет располагаться сразу за концом предыдущего.
Процедура NEW может вызываться как функция. В этом случае параметром обращения к ней является тип переменной, размещаемой в куче, а функция 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 значение указателя кучи. Освобождается участок кучи от адреса, хранящегося в PTR, до конца кучи. Одновременно уничтожается список всех свободных фрагментов, которые, возможно, были созданы процедурами DISPOSE или FREEMEM.
Функция SEG - возвращает значение типа WORD, содержащее сегмент адреса указанного объекта. Вызов:
SEG ( X )
Здесь X - выражение любого типа или имя процедуры.
Функция SIZEOF - возвращает длину в байтах внутреннего представления указанного объекта. Вызов:
SIZEOF ( X )
Здесь X - имя переменной, функции или типа. Например, везде в программе из примера 1 вместо константы SIZEOFREAL можно было бы использовать обращение SIZEOF(REAL).
Как уже отмечалось, администратор кучи - это служебная подпрограмма, которая обеспечивает взаимодействие пользовательской программы с кучей. Администратор кучи обрабатывает запросы процедур NEW, GETMEM, DISPOSE, FREEMEM и др. и изменяет значения указателей HEAPPTR и FREELIST. Указатель HEAPPTR содержит адрес нижней границы свободной части кучи, а указатель FREELIST - адрес описателя первого свободного блока. В модуле SYSTEM указатель FREELIST описан как POINTER, однако фактически он указывает на следующую структуру данных:
type
PFreeRec = ATFreeRec;
TFreeRec = record
Next : pointer;
Size : pointer
end;
Эта списочная структура предназначена для описания всех свободных блоков памяти, которые расположены ниже границы HEAPPTR. Происхождение блоков связано со случайной последовательностью использования процедур NEW-DISPOSE или GETMEM-FREEMEM («ячеистая» структура кучи). Поле NEXT, в записи TFREEREC содержит адрес описателя следующего по списку свободного блока кучи или адрес, совпадающий с HEAPEND, если этот участок последний в списке. Поле SIZE содержит ненормализованную длину свободного блока или 0, если ниже адреса, содержащегося в HEAPPTR, нет свободных блоков. Ненормализованная длина определяется так: в старшем слове этого поля содержится количество свободных параграфов, а в младшем - количество свободных байт в диапазоне 0... 15. Следующая функция преобразует значение поля SIZE в фактическую длину свободного блока:
Информация о работе Указатель и динамическая память в Турбо Паскаль