Creating "Dynamic" Arrays?

Is it possible to re-size arrays at runtime?


I came across an example of how to do one. The author is Ben Licht, who presents an age-old Pascal method of creating a dynamic array.

The trick is using a pointer to an array with a size of 1, then allocating memory for the pointer by multiplying the number of items you want in the array by the size of the array type.

Here's a sample unit I've adapted from his example:

{This unit demonstrates how to implement a dynArray}
unit U;

interface

uses
  SysUtils, WinTypes, WinProcs, Classes, Controls, Forms, Dialogs, StdCtrls;
type
  TResizeArr = array[0..0] of string;
  PResizeArr = ^TResizeArr;
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

  procedure DefineDynArray(var h : THandle;          {Handle to mem pointer}
                           NumElements : LongInt;    {Number of items in array}
                           var PArr : PResizeArr);   {Pointer to array struct}

  procedure TestDynArray;

implementation
{$R *.DFM}

{============================================================================
 Procedure that defines the dynarray. Note that the THandle and Pointer to
 the array are passed by reference. This enables them to be defined outside
 the scope of this procedure.
 ============================================================================}
procedure DefineDynArray(var h : THandle;          {Handle to mem pointer}
                         NumElements : LongInt;    {Number of items in array}
                         var PArr : PResizeArr);   {Pointer to array struct}
begin

  {Allocate Windows Global Heap memory}
  h    := GlobalAlloc(GMEM_FIXED, NumElements * sizeof(TResizeArr));
  PArr := GlobalLock(h);
end;

{============================================================================
 Procedure that uses the DefineDynArray proc. This is pretty useless, but
 provides a good example of how you can access the elements of the 'array'
 once the array is defined.
 ============================================================================}
procedure TestDynArray;
var
  MyArray : PResizeArr;
  I       : Integer;
  str     : String;
  h       : THandle;
begin
  str := '';
  DefineDynArray(h, 10, MyArray); {Define the 'array'}
  for I := 0 to 9 do
    MyArray^[I] := IntToStr(I);
  for I := 0 to 9 do
    str := str + MyArray^[I] + ',';
  ShowMessage(str);
  GlobalUnlock(h); {Must make a call to unlock the memory, then}
  GlobalFree(h);   {free the memory and invalidate the handle}
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
     TestDynArray;
end;

end.

This is a perfect example of one of those programming things that take hours to figure out, but turn out to be amazingly simple. But I should point out that it might just be simpler to use a TList, which does all of the above, but has methods to insert and delete items. It's only limited by the amount of memory you have.