16.1. Динамические переменные
Динамические переменные представляют собой указатели на области памяти, где хранятся какие–то данные. Каждая из таких переменных занимает в памяти 4 байта. Например, в разделе объявления переменных можно определить указатель на строку следующим образом:
Var PS:^String;
Знак «^» – тильда, поставленный перед типом String, обозначает описание указателя на память, которая может быть выделена строке. Переменная PS будет занимать в памяти 4 байта, в них и будет храниться адрес начала выделенной памяти для строки. Здесь под адресом будем понимать не физический адрес памяти, а особым образом рассчитанный адрес внутри участка памяти, выделенного для динамических переменных. Этот участок памяти описывается отдельным дискриптором, как это принято в защищенном режиме работы процессора. Весь процесс выделения и освобождения динамической памяти контролируется системой Delphi. Графически это можно представить так:
Память под динамические переменные выделяется и освобождается во время выполнения программы по мере необходимости. Приведем основные процедуры и функции для работы с динамическими переменными:
Procedure New(var P:Pointer); – процедура выделения памяти под динамическую переменную P. Здесь тип Pointer определяет любой указатель на область памяти. Эта процедура выделяет блок памяти такой длины, как это было указано в типе динамической переменной P. В P записывается адрес начала блока выделенной памяти;
Procedure Dispose(var P:Pointer); – процедура освобождения динамической памяти, которая ранее была выделена процедурой New для переменной P;
Procedure GetMem(var P:Pointer; Size:Integer); – процедура выделения блока динамической памяти длиной Size байт и записи адреса начала этой памяти в переменную P. Эта процедура позволяет выделять блок памяти любой длины, независимо от типа указателя P;
Procedure FreeMem(var P:Pointer; Size:Integer); – процедура освобождения динамической памяти, которая ранее была выделена переменной P процедурой GetMem;
Function AllocMem(Size:Cardinal):Pointer; – функция возвращает указатель на блок выделенной динамической памяти длиной Size байт и обнуляет эту память, в отличие от процедуры GetMem. Освобождать эту память можно процедурой FreeMem;
Var AllocMemCount:Integer; – системная переменная, которая определяет число динамических блоков памяти для данного приложения. Эта переменная доступна только для чтения;
Var AllocMemSize:Integer; – системная переменная, которая определяет общий размер всех динамических блоков памяти для данного приложения. Такие переменные позволяют контролировать процесс выделения и освобождения динамической памяти;
PS
4 байта Динамическая память
Адрес
Function SysGetMem(size:Integer):Pointer; – функция выделения системной динамической памяти. Эта память может быть доступна одновременно нескольким процессам;
Function SysFreeMem(var P:Pointer):Integer; – функция освобождения системной динамической памяти, которая ранее была выделена функцией SysGetMem;
Function Addr(X):Ponter; – функция получения адреса или указателя на любую переменную X. Эта функция эквивалентна оператору «@». Можно получить адрес переменной, записав:
P:=Addr(x); или
P:=@X;.
Процесс выделения и освобождения памяти довольно сложен и находится под контролем операционной системы. Память под динамические переменные выделяется в специальной области памяти Heap–области или так называемой «куче». Для предотвращения сильной фрагментации этой области памяти необходимо придерживаться следующего правила: освобождать память следует в обратном порядке по сравнению с ее выделением. Другими словами, если мы выделили память под переменную P1, а затем под переменную P2, то освобождать следует сначала память, выделенную под переменную P2, и только потом освобождать память, выделенную под переменную P1.
Для доступа к содержимому динамической памяти следует после имени указателя ставить символ «^» – тильда.
Рассмотрим пример программы умножения матрицы на вектор, но при этом матрицу и вектор расположим в динамической области памяти. Размер матрицы будем задавать в компоненте Edit1. Матрицу А будем выводить в компоненте StringGrid1, вектор X – в компоненте StringGrid2, а результат умножения поместим в компоненте StringGrid3. Тогда обработчик события нажатия клавиши «Вычислить» примет вид
Procedure Button1Click(Sender:Tobject);
Type Ta=array[1..1] of Extended;
// Тип одномерного массива вещественного типа
Tpa=^Ta; // Тип указателя на одномерный массив вещественного типа
Tapa=array[1..1] of Tpa; // Тип массива указателей
Tpapa=^Tapa; // Тип указателя на массив указателей
Var Px,Py:Tpa; // Указатели на массивы X и Y
Pa:Tpapa; // Указатель на массив указателей на одномерные массивы
// вещественных чисел.
i,j,n:Integer; // Внутренние переменные
Procedure MulAX(n:integer, var Px,Py:Tpa; var Pa:Tpapa);
// Процедура умножения матрицы А на вектор X, результат в векторе Y
Var i,j:Integer; s:extended; // Внутренние переменные
Begin
For i:=1 to n do Begin // Цикл по строкам
S:=0;
For j:=1 to n do // Цикл по столбцам
s:=s+Pa^[i]^[j]*Px^[j];
Py^[i]:=s; // Запоминаем результат
End;
End;
Begin // Начало раздела действий процедуры Button1Click
n:=StrToInt(Edit1.Text); // Определяем размерность массивов
with StringGrid1 do Begin // Подготовка визуальных компонентов
ColCount:=n+1;
RowCount:=n+1;
FixedCols:=1;
FixedRows:=1;
End;
with StringGrid2 do Begin
ColCount:=2;
RowCount:=n;
FixedCols:=1;
FixedRows:=0;
End;
with StringGrid3 do Begin
ColCount:=2;
RowCount:=n;
FixedCols:=1;
FixedRows:=0;
End;
GetMem(Px,n*Sizeof(extended)); // Выделение памяти для массива X
GetMem(Py,n*Sizeof(extended)); // Выделение памяти для массива Y
GetMem(Pa,n*Sizeof(Pointer));
// Выделение памяти для указателей на строки массива A
For i:=1 to n do Begin
GetMem(Pa^[i],n*Sizeof(Extended));
// Выделение памяти под строки массива A
Px^[i]:=Random; // Задание случайным образом вектора X
StringGrid2.Sells[0,i-1]:=Floattostr(i); // Оформление таблиц
StringGrid2.Sells[1,i]:=Floattostr(Px^[i]);
StringGrid1.Sells[0,i-1]:=inttostr(i);
StringGrid1.Sells[i-1,0]:=inttostr(i);
StringGrid3.Sells[i-1,0]:=inttostr(i);
For j:=1 to n do Begin
Pa^[i]^[j]:=Random; // Задание случайным образом значений массива A
StringGrid1.Sells[j,i]:=Floattostr(Pa^[i]^[j]);
End;
end;
MulAX(n,Px,Py,Pa); // Вызов процедуры умножения матрицы на вектор
For i:=1 to n do Begin
StringGrid3.Sells[1,i-1]:=Floattostr(Py^[i]); // Отображение результатов
FreeMem(Pa^[n-i+1],n*sizeof(Extended);
// Освобождение в обратном порядке памяти для строк матрицы A
End;
FreeMem(Pa,n*sizeof(Pointer));
// Освобождение массива указателей на строки массива A
FreeMem(Py,n*sizeof(extended)); // Освобождение памяти для вектора Y
FreeMem(Px,n*sizeof(Extended)); // Освобождение памяти для вектора X
End;
В данном примере размерность массивов в принципе может быть любая. Динамической памяти под массивы выделяется ровно столько, сколько нужно для заданной размерности n.
- Программирование в среде Delphi
- Программирование в среде Delphi
- 1. История развития вычислительной техники, системы счисления и единицы информации.................................................7
- 2. Структура персонального компьютера и операционные системы.........................................................................13
- 3. Основы алгоритмизации и работа в delphi..........................18
- 4. Базовые элементы delphi...................................................................26
- 5. Стандартные функции и подпрограммы................................30
- 6. Операторы delphi......................................................................................33
- 7. Операторы циклов....................................................................................35
- 18. Выделение памяти под объект и прародитель всех классов – tobject..........................................................................................84
- 19. Обработка исключительных ситуаций................................87
- 20. Основные классы и общие свойства компонентов...93
- 26. Технология com.....................................................................................129
- 1. История развития вычислительной техники, системы счисления и единицы информации
- 1.1. История развития вычислительной техники
- 1.2. Системы счисления
- 1.3. Единицы информации
- 2. Структура персонального компьютера и операционные системы
- 2.1. Структура персонального компьютера.
- 2.2. Операционные системы
- 3. Основы алгоритмизации и работа в delphi
- 3.1. Основы программирования
- 3.2. Программирование в среде Delphi
- 4. Базовые элементы delphi
- 4.1. Алфавит среды Delphi
- 4.2. Константы
- 4.3. Переменные
- 4.4. Основные типы переменных
- 4.5. Операции над переменными и константами
- 5. Стандартные функции и подпрограммы
- 5.1. Математические функции
- 5.2. Функции преобразования
- 5.3. Дополнительные системные подпрограммы и функции
- 6. Операторы delphi
- 6.1. Оператор присваивания
- 6.2. Оператор безусловной передачи управления
- 6.3. Условный оператор if
- 6.4. Оператор разветвления Case
- 6.5. Составной оператор
- 7. Операторы циклов
- 7.1. Оператор цикла For
- 7.2. Оператор цикла Repeat
- 7.3. Оператор цикла While
- 8. Работа с массивами
- 9. Работа со строками
- 9.1. Процедуры работы со строками
- 9.2. Функции работы со строками
- 10. Работа с записями
- 11. Процедуры и функции
- 12. Модуль unit
- 13. Работа со множествами
- 14. Работа с файлами
- 14.1. Текстовые файлы
- 14.2. Типированные файлы
- 14.3. Нетипированные файлы
- 15. Работа с файлами и каталогами
- 16. Динамические переменные и структуры данных
- 16.1. Динамические переменные
- 16.2. Работа со стеком
- 16.3. Работа со списками или очередями
- 16.4. Работа с деревьями
- 17. Основы объектно–ориентированного программирования
- 17.1. Объекты и классы
- 17.2. Области видимости класса
- 17.3. Свойства (Property) и инкапсуляция
- 17.4. Методы, наследование и полиморфизм
- 17.5. События (Events)
- 18. Выделение памяти под объект и прародитель всех классов – tobject
- 18.1. Выделение памяти под объект
- 18.2. Описание класса tObject
- 18.3. Операторы приведения типов классов
- 19. Обработка исключительных ситуаций
- 19.1. Два вида оператора Try
- 19.2. Программное создание исключительной ситуации
- 19.3. Основные исключительные ситуации
- 20. Основные классы и общие свойства компонентов
- 20.1. Класс tList
- 20.2. Класс tStrings
- 20.3. Общие свойства компонентов
- 21. Графические возможности delphi
- 21.1. Класс Tcanvas
- 21.2. Классы тGгарhic и тРicture
- 21.3. Классы tFont, tPen и tBrush
- 21.4. Работа с изображениями
- 22. Визуальные компоненты delphi
- 22.1. Компонент tBitBtn
- 22.2. Компоненты tDrawGrid и tStringGrid
- 22.3. Компонент tPageControl
- 22.4. Компонент tTimer
- 22.5. Компонент tGauge
- 22.6. Компонент tСolorGrid
- 23. Стандартные диалоговые окна и типовые диалоги
- 23.1. Стандартные диалоговые окна
- 23.2. Типовые диалоги
- 24. Форма, приложение и глобальные объекты
- 24.1. Форма и ее свойства
- 24.2. Объект Application
- 24.3. Глобальные объекты
- Объект ClipBoard
- Объект Screen
- Объект Printer
- 25. Межпрограммное взаимодействие
- 25.1. Обмен сообщениями
- 25.2. Динамический обмен данными
- 25.3. Совместное использование общей памяти
- 25.4. Каналы
- 25.5. Сокеты
- 26. Технология com
- 26.1. Интерфейс
- 27. Технология автоматизации
- 27.1. Основы ole Automation
- 27.2. Примеры использования серверов автоматизации
- 27.3. Компоненты ActiveX
- 28. Динамические библиотеки
- 28.1. Создание dll
- 28.2. Использование dll
- 28.3. Пример написания dll
- 29. Работа с базами данных
- 29.1. Основные определения
- 29.2. Взаимодействие приложения на Delphi с базами данных
- 29.3. Компоненты взаимодействия с базами данных
- If adoTable1.Locate(’fio,stag’,varArrayOf([’Иванов’,’10’]),[])Then …;
- 29.4. Работа с локальной базой данных
- 30. Основы языка sql
- 30.1. Составные части sql
- 30.2. Команда select
- 30.3. Пример использования запросов в Delphi
- 31. Создание собственных компонентов
- 32. Работа с реестром
- 33. Перспективы программирования в delphi
- Литература
- 220013, Минск, п.Бровки, 6