html

четверг, 1 марта 2012 г.

Динамический массив в Delphi

1. Динамические массивы в Delphi не имеют фиксированного размера . Чтобы объявить такой массив необходимо  записать:

var da_MyArray : array of integer;

Как  видим , мы просто говорим Delphi, что нам нужен одномерный массив типа Integer, а об его размере мы скажем  когда нибудь потом.

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

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);
   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
Окно программы примера 1

Окно программы примера 2
Окно программы примера 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 

  Посты по теме :





Комментариев нет: