1. Динамические массивы в Delphi не имеют фиксированного размера . Чтобы объявить такой массив необходимо записать:
var da_MyArray : array of integer;
Как видим , мы просто говорим Delphi, что нам нужен одномерный массив типа Integer, а об его размере мы скажем когда нибудь потом.
При таком объявлении память не выделяется, поэтому мы можем объявить много таких динамических массивов, не особо беспокоясь об объеме занимаемой памяти, и использовать любой динамический массив по мере надобности.
2. Для выделения памяти для динамического массива в Delphi используется процедура SetLength:
2. Для выделения памяти для динамического массива в Delphi используется процедура SetLength:
SetLength(da_MyArray,20);
После вызова этой процедуры будет выделена память для 20 элементов массива, которые будут проиндексированы от 0 до 19 (обратите внимание: индексирование начинается с нуля, а не с единицы!).
После этого можно работать с динамическим массивом- присваивать ему значения, производить с элементами различные вычисления, вывод на печать и т.д.
Например
da_MyArray[0] := 5 ;
da_MyArray[9] := 9 ;
da_MyArray[1] := da_MyArray[0]+ da_MyArray[9] ;
3. Как только динамический массив был распределен, вы можете передавать массив стандартным функциям Length, High, Low и SizeOf Функция Length возвращает число элементов в динамическом массиве, High возвращает самый высокий индекс массива (то есть Length - 1), Low возвращает 0. В случае с массивом нулевой длины наблюдается интересная ситуация: High возвращает -1, а Low - 0, получается, что High меньше Low. :) Функция SizeOf всегда возвращает 4 - длина в байтах памяти указателя на динамический массив
iHigh := High (da_MyArray3);
iLow := Low (da_MyArray3);
правильно
WriteFile(FHandle, da_MyArray02[0], Length(da_MyArray02), dwTemp, nil)
неправильно
WriteFile(FHandle, da_MyArray02, Length(da_MyArray02), dwTemp, nil)
5. Рассмотрим пример присваивания динамических массивов одного другому
После этих манипуляций da_A[0] равно 4. Дело в том , что при присвоении da_A:=da_B не происходит копирование т.к. da_A, da_B, это всего лишь указатели на область памяти. Для копирования необходимо использовать функцию Copy.
6. Рассмотрим пример копирования динамических массивов с использованием функции Copy
После этих манипуляций da_A[0] равно 3. После функции Copy da_A и da_B указывают на разные области памяти, поэтому при изменении da_B в da_A ничего не происходит и его значения остаются неизменными.
7. Динамические массивы (например, array of Integer) в Delphi в памяти расположены следующим образом. Библиотека runtime добавляет специальный код, который управляет доступом и присваиваниями. В участке памяти ниже адреса, на который указывает ссылка динамического массива, располагаются служебные данные массива: два поля - число выделенных элементов и счётчик ссылок (reference count).
Если, как на диаграмме выше, N - это адрес в переменной динамического массива, то счётчик ссылок массива лежит по адресу
Для каждой добавляемой ссылки (т.е. при присваивании, передаче как параметр в подпрограмму и т.п.) увеличивается счётчик ссылок, а для каждой удаляемой ссылки (т.е. когда переменная выходит из области видимости или при переприсваивании или присваивании nil) счётчик уменьшается.
8. Написал 2 программы, которые иллюстрируют теоретические сведения по динамическим массивам , приведенным в посте.
Скачать программы- примеры с исходными кодами здесь : Dynamic-Array.rar
Использовались функции SetLength, High, Low, Length, SizeOf, OpenFile, WriteFile, SetFilePointer, ReadFile, CloseHandle, ShellExecute, IntToStr, IntToHex, Integer, Copy, Ptr
9. Полезные ссылки:
-- Работа с указателями
-- ReadFile & Array of Byte, Можно так делать и как правильно?
-- Динамические массивы 4
Посты по теме :
После этого можно работать с динамическим массивом- присваивать ему значения, производить с элементами различные вычисления, вывод на печать и т.д.
Например
da_MyArray[0] := 5 ;
da_MyArray[9] := 9 ;
da_MyArray[1] := da_MyArray[0]+ da_MyArray[9] ;
3. Как только динамический массив был распределен, вы можете передавать массив стандартным функциям Length, High, Low и SizeOf Функция Length возвращает число элементов в динамическом массиве, High возвращает самый высокий индекс массива (то есть Length - 1), Low возвращает 0. В случае с массивом нулевой длины наблюдается интересная ситуация: High возвращает -1, а Low - 0, получается, что High меньше Low. :) Функция SizeOf всегда возвращает 4 - длина в байтах памяти указателя на динамический массив
iHigh := High (da_MyArray3);
iLow := Low (da_MyArray3);
iLength := Length (da_MyArray3);
iSizeOf := SizeOf (da_MyArray3);
4. Доступ к данным динамических массивов с помощью низкоуровневых процедур типа ReadFile или WriteFile , или любых других подпрограмм, получающих доступ сразу ко всему массиву, часто выполняется неправильно. Для обычного массива (его часто называют также статическим массивом - в противоположность динамическому массиву) переменная массива тождественна его данным. Для динамического массива это не так - переменная это указатель. Так что если вы хотите получить доступ к данным динамического массива - вы не должны использовать саму переменную массива, а использовать вместо неё первый элемент массива.правильно
WriteFile(FHandle, da_MyArray02[0], Length(da_MyArray02), dwTemp, nil)
неправильно
WriteFile(FHandle, da_MyArray02, Length(da_MyArray02), dwTemp, nil)
5. Рассмотрим пример присваивания динамических массивов одного другому
var da_A,da_B: array of integer; begin SetLength(da_A,2); SetLength(da_B,2); da_A[0]:=2; da_B[0]:=3; da_A:=da_B; da_B[0]:=4; end;
После этих манипуляций da_A[0] равно 4. Дело в том , что при присвоении da_A:=da_B не происходит копирование т.к. da_A, da_B, это всего лишь указатели на область памяти. Для копирования необходимо использовать функцию Copy.
6. Рассмотрим пример копирования динамических массивов с использованием функции Copy
var da_A,da_B: array of integer; begin SetLength(da_A,2); SetLength(da_B,2); da_A[0]:=2; da_B[0]:=3; da_A:=Copy (da_B); da_B[0]:=4; end;
После этих манипуляций da_A[0] равно 3. После функции Copy da_A и da_B указывают на разные области памяти, поэтому при изменении da_B в da_A ничего не происходит и его значения остаются неизменными.
7. Динамические массивы (например, array of Integer) в Delphi в памяти расположены следующим образом. Библиотека runtime добавляет специальный код, который управляет доступом и присваиваниями. В участке памяти ниже адреса, на который указывает ссылка динамического массива, располагаются служебные данные массива: два поля - число выделенных элементов и счётчик ссылок (reference count).
Расположение динамического массива в памяти |
Если, как на диаграмме выше, N - это адрес в переменной динамического массива, то счётчик ссылок массива лежит по адресу
N - 8
, а число выделенных элементов (указатель длины) лежит по адресу N - 4
. Первый элемент массива (сами данные) лежит по адресу N
.Для каждой добавляемой ссылки (т.е. при присваивании, передаче как параметр в подпрограмму и т.п.) увеличивается счётчик ссылок, а для каждой удаляемой ссылки (т.е. когда переменная выходит из области видимости или при переприсваивании или присваивании nil) счётчик уменьшается.
8. Написал 2 программы, которые иллюстрируют теоретические сведения по динамическим массивам , приведенным в посте.
Окно программы примера 1 |
Окно программы примера 2 |
Скачать программы- примеры с исходными кодами здесь : Dynamic-Array.rar
Использовались функции SetLength, High, Low, Length, SizeOf, OpenFile, WriteFile, SetFilePointer, ReadFile, CloseHandle, ShellExecute, IntToStr, IntToHex, Integer, Copy, Ptr
9. Полезные ссылки:
-- Работа с указателями
-- ReadFile & Array of Byte, Можно так делать и как правильно?
-- Динамические массивы 4
Посты по теме :
Комментариев нет:
Отправить комментарий