рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

Указатели и динамическая память

Указатели и динамическая память - раздел Транспорт, От автора Указателями Называются Переменные И Константы, Значен...

Указателями называются переменные и константы, значениями которых являются адреса. Различаются два вида указателей - обобщенные указатели и типизированные указатели. Обобщенные указатели имеют тип Pointerи могут содержать адреса любых объектов. Типизированные указатели имеют тип ^базовый тип и содержат только адреса объектов базового типа. Базовый тип может быть любым, кроме файлового. Существует одна константа-указательNil, равная некоторому несуществующему адресу. Указателям можно присваивать адреса переменных, для этого служит операция “адрес”: @имя переменной. Существует и обратная операция - “значение”: указатель^, результат этой операции есть значение, записанное по адресу, который содержит указатель. Операция “значение” неприменима к обобщенным указателям. Указателям можно присваивать адреса переменных соответствующего типа и другие указатели того же типа (или обобщенные указатели). Обобщенному указателю можно присвоить любой указатель. Никакие арифметические операции к указателям не применимы, их нельзя вводить и выводить. Запишем программу, выполняющую простейшие операции с указателями:

 

Var

b : Byte;

w : Word;

pB : ^Byte;

pW : ^Word;

Begin

pB:=@b; {теперь в указателе pB хранится адрес переменной b, b и pB^ - одна и та же переменная}

pW:=@w; {в указателе pW хранится адрес переменной w}

Read(pB^,pW^);

WriteLn(pB^,' ',pW^,' ',b,’ ‘,w); {дважды вывели значения b и w}

End.

 

Как видите, конструкция указатель^ может применяться точно так же, как и имя переменной соответствующего типа. Для работы с адресами существуют четыре стандартных функции:

1.Function Addr(X): Pointer - возвращает адрес переменной X, по существу аналогична операции “адрес”.

2. Function Seg(X): Word - возвращает сегментную часть адреса переменной X.

3. Function Ofs(X): Word - возвращает смещение адреса переменной X. (Полный адрес занимает 4 байта, значение первых двух называют сегментом, а последних - смещением.)

4. Function Ptr(Seg,Ofs: Word): Pointer - возвращает адрес, состоящий из сегмента Seg и смещения Ofs. Запишем пример использования этих функций:

 

Const L : LongInt = 123456789;

Var p : Array [0..3] Of ^Byte;

i : Byte;

Begin For i:=0 To 3 Do p[i]:=Ptr(Seg(L),Ofs(L)+i); {теперь элементы массива p равны адресам байтов, из которых состоит константа L}

WriteLn(p[0]^:4,p[1]^:4,p[2]^:4,p[3]^:4);

End.

Программа выведет байтыL в последовательности от младшего к старшему: 21 205 91 7. Впрочем, нам известны еще два способа решения этой задачи - с помощью вариантного поля записи и с помощью описателя Absolute. Запишем соответствующие программы.

 

Const R : Record {вариантное поле записи}

Case Byte Of

1: (L: LongInt);

2: (b:Array[0..3] Of Byte) End

=(L:123456789);

Begin With R Do WriteLn(b[0]:4,b[1]:4,b[2]:4,b[3]:4); End.

 

Const L: LongInt=123456789;

Var b:Array[0..3] Of Byte Absolute L; {описатель Absolute}

Begin

WriteLn(b[0]:4,b[1]:4,b[2]:4,b[3]:4);

End.

 

Приведенные примеры не очень содержательны, так как указатели, главным образом, используются для работы с динамической памятью. Динамическая память (или хип) - это область памяти, которую программа может использовать для размещения динамических переменных. В отличие от обычных (или статических) переменных, память под которые отводится компилятором до начала выполнения программы и освобождается после ее завершения, динамическая память распределяется и освобождается в процессе выполнения программы. Необходимость использования динамической памяти обусловлена, в частности, ограниченностью сегмента данных и стека: все статические переменные, описанные в программе или в подпрограмме, не могут занимать более64К памяти. Динамическая память, как правило, имеет гораздо больший объем. Перечислим стандартные функции и процедуры для работы с хипом:

5. Function MemAvail : LongInt - возвращает размер свободной динамической памяти в байтах.

6. Function MaxAvail : LongInt - возвращает размер наибольшего свободного участка динамической памяти в байтах.

7. Procedure New(Var p:указатель) - отводит участок динамической памяти и присваивает указателю p адрес этого участка. Размер участка определяется базовым типом указателя.

8. Procedure Dispose(Var p:указатель) - освобождает участок динамической памяти, адрес которого хранится в указателе, после выполнения процедуры значение указателя не определено.

9. Procedure Mark(Var p:Pointer) - записывает состояние динамической памяти в указатель p.

10. Procedure Release(Var p:Pointer) - возвращает динамическую память к состоянию, записанному в указателе p.

11. Procedure GetMem(Var p:Pointer; Size: Word) - распределяет участок динамической памяти размером Size байт и записывает его адрес в указатель p.

12. Procedure FreeMem(Var p:Pointer; Size: Word) - освобождает память, распределенную процедурой GetMem.

Приведем еще две процедуры, имеющие отношение к указателям:

13. Procedure Move(Var Source,Dest; Count: Word) - копирует Count байт из переменной Source в переменную Dest, причем можно использовать и имена переменных, и указатели с операцией “значение”.

14. Procedure FillChar(Var X; Count:Word; Value) - заполняет Count байт переменной X значением Value. Value может быть либо типа Byte, либо типа Char. Приведем пример использования последних двух процедур безотносительно к динамической памяти : пусть в программе описаны массивы A длиной 100 и B длиной 1000 элементов, и требуется скопировать массивA в последние 100 элементов B, а остальные элементыB занулить:

 

FillChar(B,SizeOf(B),0); Move(A,B[901],SizeOf(A));

 

Теперь запишем программу, использующую массив, размещенный в динамической памяти:

 

Const Nmax=10000;

Type Massiv = Array[1..Nmax] Of Real;

Var

p : ^Massiv;

i : Word;

Begin

If MaxAvail<SizeOf(Massiv) Then Begin

WriteLn('Не хватает памяти');

Halt(0);

End;

New(p);

Randomize;

For i:=1 To Nmax Do p^[i]:=Random;

For i:=1 To Nmax Do Write(p^[i]:5);

Dispose(p);

End.

 

С динамическим массивом можно обращаться точно так же, как и с обычным, только вместо имени массива используется конструкция p^. Но, пользуясь подобными алгоритмами, мы все равно не можем организовать динамический массив размером более 64К байт. Пусть, например, программа должна работать с целочисленной матрицей размером 200 на 200. Оператор Type Massiv=Array[1..200,1..200] Of LongInt; является синтаксически неправильным - Паскаль запрещает описывать какие-либо объекты (и даже типы объектов), размер которых превосходит 64К байт. Применим другой способ - опишем одномерный массив из двухсот указателей, каждый из которых будет содержать адрес одной строки матрицы.

 

Const N=200;

Type

T_Row=Array[1..N] Of LongInt; {строка матрицы}

T_Massiv=Array[1..N] Of ^T_Row; {массив указателей на строку}

Var

p : T_Massiv;

i,j : Word;

Begin

For i:=1 To N Do GetMem(p[i],SizeOf(T_Row));{выделим память для каждой строки, и адрес этой памяти присвоим соответствующему элементу p}

Randomize;

For i:=1 To N Do

For j:=1 To N Do

p[i]^[j]:=Random(1000); {p[i] - адрес i-й строки; p[i]^ - сама i-я строка; p[i]^[j] - элемент матрицы с индексами i,j}

For i:=1 To N Do

For j:=1 To N Do Write(p[i]^[j]:4);

WriteLn;

For i:=1 To N Do FreeMem(p[i],SizeOf(T_Row));{освободим взятую нами память}

End.

 

Теперь, когда мы умеем пользоваться указателями, рассмотрим еще три подпрограммы модуля Graph, в свое время пропущенные нами.

Function ImageSize(x1,y1,x2,y2: Integer):Word; - возвращает размер памяти (в байтах), необходимой для хранения прямоугольного участка графического экрана, x1,y1,x2,y2 задают диагональ этого прямоугольника.

Procedure GetImage(x1,y1,x2,y2: Integer; VarBitMap); - копирует прямоугольный участок графического экрана в переменную BitMap.

Procedure PutImage(x,y: Integer; VarBitMap;WriteMode: Word); - выводит на графический экран изображение, записанное в переменной BitMap, левый верхний угол изображения совмещается с точкой x,y на экране. Параметр WriteMode имеет тот же смысл, что и в процедуре SetWriteMode. Эти средства позволяют создавать не очень сложные анимационные программы. Мы рассмотрим самый простой пример использования этих подпрограмм.

 

Uses Graph,Crt;

Var

Gd,Gm,i,j : Integer;

p : Pointer;

s : Word;

Const L=40;

Begin

Gd:=Detect;

InitGraph(Gd,Gm,'');

{нарисуем какую-нибудь картинку в квадрате со стороной L, например зеленый квадрат в желтой рамке с синим кружком посередине}

SetFillStyle(1,2);

Bar(0,0,L-1,L-1);

SetColor(14);

Rectangle(0,0,L-1,L-1);

SetColor(1);

SetFillStyle(1,1);

FillEllipse(L Div 2,L Div 2,L Div 4,L Div 4);

{определим размер памяти, необходимый для хранения этой картинки}

s:=ImageSize(0,0,L-1,L-1);

{выделим место в хипе}

GetMem(p,s);

{скопируем изображение в хип}

GetImage(0,0,L-1,L-1,p^);

{а теперь очень быстро заполним весь экран такими картинками}

For i:=0 To GetMaxX Div L Do

For j:=0 To GetMaxY Div L Do

PutImage(i*L,j*L,p^,CopyPut);

Repeat Until KeyPressed;

{освободим хип}

FreeMem(p,s);

CloseGraph;

End.

– Конец работы –

Эта тема принадлежит разделу:

От автора

B r... Теперь мы можем присвоить переменным их значения...

Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Указатели и динамическая память

Что будем делать с полученным материалом:

Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Все темы данного раздела:

От автора
Первое издание этой книги вышло в свет в 1997 году и довольно быстро стало библиографической редкостью. Автор несколько неожиданно для себя обнаружил, что книга пользуется черезвычайно высоким спро

Round(x) - округленное до целого вещественное число, преобразованное к типуLongInt
6. Sqr(x) - квадрат числа 7. Sqrt(x) - квадратный корень 8. Exp(x) - экспонента 9. Ln

Символьный тип данных
Для хранения символьной информации в Паскале предусмотрен специальный тип данных Char. Допустимы переменные, нетипизированные и типизированные константы такого типа. Данные типа

Caseвыражение Of
список значений : оператор/блок .................................. список значений: оператор/блок

Процедуры и функции. Сфера действия описаний
В языке Паскаль (как вы уже поняли из предыдущего материала) существуют понятия процедуры и функции. Процедуры и функции можно определить как замкнут

Открытые массивы и нетипизированные параметры
Из предыдущего раздела мы узнали, что параметры подпрограмм описываются как [Var] имя : имя типа , это правда, но не вся правда - существует еще два

Множества
Понятие множества в Паскале очень близко к математическому определению: множество - это совокупность однотипных неиндексированных объектов. Множества

Графические средства языка Паскаль
Монитор персонального компьютера может работать в двух режимах - текстовом и графическом. Все, что мы делали до сих пор, мы делали в текстовом режиме. Текстовый экран содержит 2000 знако

Особенности вещественных вычислений
В отличие от целочисленных выражений, которые всегда вычисляются точно, вещественные выражения дают приближенный результат и вещественные переменные содержат приближенные значения. Это обстоятельст

Case тип Of
константа 1 : (описание поля); константа 2 : (описание поля); .....................

Модуль Crt
Crt - еще один стандартный модуль Паскаля, в котором содержатся разнообразные средства консольного ввода-вывода (то есть ввода с клавиатуры и вывода на текстовый экран). Процедуры

Var TextAttr : Byte
В ней содержится текущий цвет фона и цвет символов, используемые при выводе на экран процедурами Write иWriteLn. Изменив эту переменную, вы задаете новый

Другие средства обработки файлов и модуль DOS
Для того чтобы определить, есть ли на диске файл с заданным именем, удобно использовать уже известную нам стандартную функцию IOResult , которая возвращает ноль при успешном завершении последней оп

Type SearchRec=Record
Fill : Array[1..21] of Byte; Attr : Byte; Time : LongInt; Size : LongInt; Name : Stri

Процедурные типы
Язык Паскаль позволяет использовать в программе данные типа “процедура” или типа “функция”. Такие данные можно передавать как аргументы подпрограмм, можно описывать и использовать массивы процедур

Динамические структуры: списки, деревья
Примеры программ, использующих динамические массивы, приведенные в предыдущей главе, все еще были плохими. Для того чтобы использовать динамические массивы таким образом, мы должны заранее знать ра

Открытые строки
  Открытыми строками, или длинными строками, или C-строками, называются символьные последовательности длиной до 65535 символов, ограниченные справа нуль-символ

Использование командной строки и вызов внешних программ
Паскаль позволяет передавать информацию в программу при ее запуске через командную строку. Для этого служат две стандартные функции -ParamCount и ParamStr.

Обработка программных прерываний
Программное прерывание - это ситуация, возникающая, когда дальнейшее выполнение программы невозможно. Например, деление на ноль, переполнение, ошибка Range check error, обращение по неверному адрес

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

Type имя типа=Object
описание полей описание методов End; Поля объектов описываются так же, как поля записей, а описание метода - это заголовок процедуры или функции. Сами методы распол

Рекурсия и динамическое программирование
В этом и всех последующих разделах речь пойдет уже не о языке программирования Паскаль, а о задачах, которые вы можете решать с помощью этого языка, о наиболее интересных и полезных алгоритмах и пр

Рекурсия и стек отложенных заданий
Рекурсивные алгоритмы далеко не всегда неэффективны, как можно подумать, прочитав предыдущий раздел. Во многих задачах рекурсивные процедуры и функции очень полезны, кроме того, они исключительно п

Стеки и очереди
Значение стека как структуры данных в программировании не исчерпывается лишь стеком отложенных заданий. В этом разделе мы решим с помощью стека задачу о вычислении значения арифметического выражени

Комбинаторные алгоритмы
В этом разделе мы рассмотрим три наиболее важные задачи комбинаторики: нахождение всех подмножеств множества из n элементов; нахождение всех выборок по m элементов из n элементов и нахождение всех

Бинарные деревья
В этом разделе мы рассмотрим различные алгоритмы обхода бинарного дерева. К алгоритмам создания бинарного дерева мы обратимся несколько позже, а пока будем считать, что дере

Упорядоченные бинарные деревья и приоритетные очереди
Упорядоченным бинарным деревом, или бинарным деревом поиска, называют дерево, в любой части которого элементы левого поддерева меньше корневого элеме

Алгоритмы сортировки
В этом разделе мы рассмотрим различные алгоритмы решения задачи сортировки. Задача сортировки ставится следующим образом: дана последовательность записей R1,R

Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • Популярное
  • Облако тегов
  • Здесь
  • Временно
  • Пусто
Теги