Язык DelphiПеременные - указатели |
Уроки Delphi
1. Первая программа
2. Использование компонентов
3. События Delphi
4. Типы данных Delphi
5. Создание своих типов данных
6. Выражения и операторы
7. Работа с файлами в Delphi
8. Дополнительные формы
9. Подпрограммы в Delphi
10. Исключительные ситуации
11. Взаимодействие приложения с пользователем
12. Указатели в Delphi
13. Обзор компонентов
14. Работа со строками
15. Создание интерфейса
16. Графика в Delphi
17. Многопоточность в Delphi
18. Динамическое создание
компонентов Поиск по сайту Это важно:
Метод Application.ProcessMessages;
Это полезно:
Параметр Sender в обработчиках событий;
Бояться не надо |
Как следует из названия, переменные - указатели это особый тип переменных, которые не содержат значения, а указывают на них - на ту ячейку памяти, где они фактически располагаются. И хотя справедливо считается, что использование указателей может приводить к трудно контролируемым ошибкам в программе, всё же переменные - указатели это очень эффективный инструмент для управления объектами в оперативной памяти компьютера. Описание переменных - указателейУказатель описывается ключевым словом Pointer. По первой букве ключевого слова принято называть переменные - указатели с первой буквы P:
var PIndexer: Pointer;//нетипизированный указатель
Ключевым словом Pointer задаётся так называемый нетипизированный указатель, по аналогии с нетипизированным файлом. Нетипизированный указатель содержит просто адреc некой ячейки памяти. Объект, располагающийся начиная с этой ячейки, соответственно может быть совершенно любого типа и размера. Также в Delphi существуют и типизированные указатели. Они могут указывать на объект соответствующего типа и размера. Именно "могут указывать", потому что это по прежнему адрес одной - первой ячейки области памяти, где располагается объект. И далее его использование в программе зависит от программиста! Итак, типизированный указатель описывается ключевым словом означающим данный тип, перед которым ставится значок ^ :
var PInteger: ^Integer;//указатель на переменную целого типа Также можно описать любой свой тип, и задать переменную-указатель данного типа:
type TMyType = Record Естественно, можно определить тип, для описания через него переменных - указателей. Делается это в том числе и потому, что, например, в процедурах и функциях в качестве параметров можно использовать только заранее описанный тип данных. Например, следующее описание задаёт функцию с параметром, являющимся указателем ранее описанного типа, результат которой также является указателем данного типа:
type TPMyPointer = ^TMyType; Ну вот, надеюсь теперь вы не боитесь разнообразных вариантов описания таких переменных как указатели. Использование переменных - указателейИспользование указателей предполагает:
1. Указателю можно присвоить значение другого указателя. В результате оба указателя будут указывать на одну и ту же ячейку памяти. Также указателю можно присвоить пустое значение с помощью ключевого слова nil :
var P1, P2: Pointer;
Указатель со значением nil не адресует никакой ячейки памяти и единственное, что с ним можно сделать - это сравнить с другим указателем или со значением nil .2. Значение типизированного указателя можно увеличить или уменьшить на размер области памяти, занимаемой объектом данного типа. Для этого служат операции инкремента и декремента:
type P: ^Integer;
Попытка выполнить операциии inc либо dec с нетипизированным указателем вызовет ошибку на этапе компиляции, так как компилятору неизвестно, насколько именно изменять значение указателя.3. Процедурой New можно создать область памяти сответствующего типа и присвоить её адрес указателю (инициировать указатель):
var PInt: ^Integer;
Поскольку с областью памяти, созданной с помощью процедуры New , не связана ни одна переменная, но там содержится реальное используемое значение, то можно считать, что это значение связано с некой "безымянной переменной". Обращаться к ней по имени переменной невозможно, а можно оперировать только используя указатель.Также задать указателю адрес объекта можно с помощью операции, называемой "взятие адреса", которая обозначается значком @ . При этом создавать область памяти уже не нужно, так как она создана предварительным описанием данного объекта:
var MyVar: TMyType;//Описание переменной, при этом выделяется область памяти соответствующего размера
4. Если область памяти уже создана и её адрес присвоен указателю, то в ячейку памяти, адресуемую данным указателем, можно записать значение объекта, соответствующего типу указателя. Для этого служит операция, обозначаемая также значком ^ , стоящим после имени указателя, например: P^ . Эта операция называется "разыменование указателя". Также с помощью этой операции со значением в данной ячейке памяти можно делать всё что нужно:
var MyVar: Integer;
С обычными переменными всё просто, но возникает вопрос, как получить значение по адресу указателя, если тип переменной - запись с несколькими полями? Аналогично:
type TMyRec = Record
А теперь уберите стрелку возле PRec: PRec.S:='Строка данных'; Вы увидите, что никакой ошибки ни компилятор, ни выполнение программы не показали! Выходит, выражения PRec^.S и PRec.S аналогичны.Далее, а как получить значение, если указатель это элемент массива, например:
var PArray: Array[1..100] of ^Integer; Ни PArray^[10] , ни PArray[10]^ не являются правильными выражениями. Ну конечно, нужно использовать скобки:
X:=(PArray[10])^;
5. Память, выделенную процедурой New, всегда нужно явно освобождать. Освободить область памяти, адресуемую указателем, инициированным с помощью New, можно процедурой Dispose :
var MyVar: TMyType;
При выполнении процедуры Dispose указатель снова приобретает неопределённое значение, не равное даже nil, и его использование может привести к неопределённым результатам, даже к краху программы. Взаимодействие приложения с пользователем
В начало урока
Обзор компонентов Delphi |
© 2023 Delphi-Manual.ru - Уроки Delphi начинающим с нуля |