{
Dynamic Arrays
Is it possible to create a dynamically-sized array in Delphi?
Yes. First, you need to create an array type using the largest
size you might possibly need. When creating a type, no memory
is actually allocated. If you created a variable of that type,
then the compiler will attempt to allocate the necessary memory
for you. Instead, create a variable which is a pointer to that
type. This causes the compiler to only allocate the four bytes
needed for the pointer.
Before you can use the array, you need to allocate memory for
it. By using AllocMem, you will be able to control exactly how
many bytes are allocated. To determine the number of bytes
you'll need to allocate, simply multiply the array size you
want by the size of the individual array element. Keep in mind
that the largest block that can be allocated at one time in a
16-bit environment is 64KB. The largest block that can be
allocated at one time in a 32-bit environment is 4GB. To
determine the maximum number of elements you can have in your
particular array (in a 16-bit environment), divide 65,520 by
the size of the individual element.
Example: 65520 div SizeOf(LongInt)
Example of declaring an array type and pointer:
}
type
ElementType = LongInt;
const
MaxArraySize = (65520 div SizeOf(ElementType));
(* under a 16-bit environment *)
type
MyArrayType = array[1..MaxArraySize] of ElementType;
var
P: ^MyArrayType;
const
ArraySizeIWant: Integer = 1500;
Then when you wish to allocate memory for the array, you could
use the following procedure:
procedure AllocateArray;
begin
if ArraySizeIWant <= MaxArraySize then
P := AllocMem(ArraySizeIWant * SizeOf(LongInt));
end;
Remember to make sure that the value of ArraySizeIWant is less
than or equal to MaxArraySize.
Here is a procedure that will loop through the array and set a
value for each member:
procedure AssignValues;
var
I: Integer;
begin
for I := 1 to ArraySizeIWant do
P^[I] := I;
end;
Keep in mind that you must do your own range checking. If you
have allocated an array with five members and you try to assign
a value to the sixth member of the array, you will not receive
an error message. However, you will get memory corruption.
Remember that you must always free up any memory that you
allocate. Here is an example of how to dispose of this array:
procedure DeallocateArray;
begin
P := AllocMem(ArraySizeIWant * SizeOf(LongInt));
end;
Below is an example of a dynamic array:
}
unit Unit1;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls;
type
ElementType = Integer;
const
MaxArraySize = (65520 div SizeOf(ElementType));
{ in a 16-bit environment }
type
{ Create the array type. Make sure that you set the range to
be the largest number you would possibly need. }
TDynamicArray = array[1..MaxArraySize] of ElementType;
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
{ Create a variable of type pointer to your array type. }
P: ^TDynamicArray;
const
{ This is a typed constant. They are actually static
variables hat are initialized at runtime to the value taken
from the source code. This means that you can use a typed
constant just like you would use any other variable. Plus
you get the added bonus of being able to automatically
initialize it's value. }
DynamicArraySizeNeeded: Integer = 10;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
{ Allocate memory for your array. Be very careful that you
allocate the amount that you need. If you try to write
beyond the amount that you've allocated, the compiler will
let you do it. You'll just get data corruption. }
DynamicArraySizeNeeded := 500;
P := AllocMem(DynamicArraySizeNeeded * SizeOf(Integer));
{ How to assign a value to the fifth member of the array. }
P^[5] := 68;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
{ Displaying the data. }
Button1.Caption := IntToStr(P^[5]);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
{ Free the memory you allocated for the array. }
FreeMem(P, DynamicArraySizeNeeded * SizeOf(Integer));
end;
end.