Как это работает?
Чтобы грамотно применять динамические массивы, необходимо разобраться в том, как они работают. Для этого выведем на экран размер массива из 100 элементов (целых чисел):
SetLength(А, 100); write(sizeof(А)); write(100*sizeof(integer));
Вы с удивлением обнаружите, что программа выводит числа 4 и 200, т. е. функция sizeof считает, что размер массива равен 4 байтам, хотя на самом деле 100 целых переменных должны занимать 200 байтов. Более того, величина sizeof (А) не зависит от фактического размера массива. Поэтому можно сделать вывод, что размер элементов тут вообще не учитывается.
На самом деле, в переменной А хранится адрес массива в памяти (рис. 6.2), который действительно занимает 4 байта. Таким образом, фактически А — это указатель.
Рис. 6.2
Если массив имеет нулевой размер, этот указатель равен нулю (нулевой адрес в Паскале обозначается nil).
Что из этого следует? Представьте, например, что мы построили структуру, которая состоит из массива (поле data) и количества используемых элементов в нём (поле size):
type TArray=record data: array of integer; size: integer; end;
Допустим создана переменная типа TArray:
var A: TArray;
для которой выделен в памяти внутренний массив data и заполнен целыми числами:
SetLength(A.data, 10) ; for i:=0 to 9 do A.data[i]:=i; A.size:=10;
Что будет, если мы попытаемся сохранить такую структуру в типизированном файле? Несложно понять, что в файл запишутся только элементы структуры, т. е. адрес массива data и количество элементов size. Сами элементы не входят в структуру, поэтому сохранены не будут. Если после этого мы прочитаем из файла такую структуру, адрес data будет недействителен и использовать его нельзя. Поэтому при сохранении в файле структур с динамическими полями нужно принимать специальные меры по сохранению содержимого массивов.
Динамическая матрица — это указатель на массив указателей:
var A: array of array of integer;
Если применить к ней процедуру SetLength с одним параметром
SetLength(А,10);
то в памяти будет выделен массив указателей на строки, причём память под сами строки не выделяется. То есть А[1] (строка матрицы с индексом 1) — это указатель, к которому можно «привязать» динамический массив любого размера, например так:
for i:=0 to High(A) do SetLength(A[i],i+1);
Таким образом, мы получили матрицу, где все строки имеют разную длину:
writeln(Length(А[0])); {=1} writeln(Length(А[9])); {= 10}
Следующая страница Вопросы и задания