dynamic array sizing

Q:  Is there any way to dynamically redimension an array?

A:  When you dynamically allocate space for an array, you *can* dynamically allocate the size as needed.  e.g.

 type
  TIntegerArray = array[0..32767] of integer;  {Types don't allocate memory }
  PIntegerArray = ^TIntegerArray;
 var
  I1,I2 : PIntegerArray;
 begin
  GetMem(I1,500*SizeOf(Integer));  { I1 now points to a 500 element array }
  GetMem(I2,1000*SizeOf(Integer)); { I2 now points to a 1000 element array }
...

Ok, now *THIS* kind of variable-sized array has been available in Pascal for many a long year. That is, the kind where you decide the size at run-time but don't change it. Here is an example that works with records:  E.g.

TYPE
  VarArray = Array[0..65520 DIV SizeOf(MyRecord)] OF MyRecord;
  ptrVarArray = ^VarArray;
VAR
  MyArray : ptrVarArray;
  GetMem(MyArray, NumNeeded*SizeOf(MyRecord));
 

       See? You define an array TYPE as large as possible, given the almost-64k limit on the size of a single variable. You define a pointer to that type. And you allocate just enough memory to hold the actual number needed.

FWIW, You can definitely use a TList too, but you'll need to define a simple OBJECT that holds your variant record, because TLists only hold TObjects and their descendants.

***********************************

Here is a later post on C-Serve:

ReAllocMem comes closest. You allocate your array on the heap with some incantations like

 Type
   TIntArray = Array [0..High(Word) div Sizeof(Integer) -1] of Integer;
   { declares the maximum size possible for an array of Integers }
   PIntArray = ^TIntArray;

 Procedure AllocArray( Var pArr: PIntArray; items: Word;
                       Var maxIndex: Word);
   Begin
     If items > 0 Then Begin
       GetMem( pArr, items * Sizeof( Integer ));
       maxIndex := Pred( items );
     End
     Else
       pArr := Nil;
   End;

 Procedure ReDimArray( Var pArr: PIntArray; newItems: Word;
                       Var maxIndex: Word );
   Begin
     If pArr = Nil Then
       AllocArray( pArr, newItems, maxIndex )
     Else Begin
       ReAllocMem( pArr, Succ(maxIndex)*Sizeof(Integer),
                   newItems*Sizeof(Integer));
       maxIndex := Pred( newItems );
     End;
   End;

 Procedure DisposeArray( Var pArr: PIntArray; maxIndex: Word );
   Begin
     FreeMem( pArr, Succ(maxIndex)*SizeOf(Integer));
   End;

 Var
  pMyArray: PIntArray;
  maxIndex, i: Word;

 Begin
   try
     AllocArray( pMyArray, 100, maxIndex );
     For i:= 0 To maxIndex Do
       pMyArray^[i] := i;
     ...
     RedimArray( pMyArray, 200, maxIndex );
     For i:= 0 To maxIndex div 2 Do
       pMyArray^[Succ(maxIndex div 2)+i] := Sqr(pMyArray^[i]);
     ....
   finally
     DisposeArray( pMyArray, maxIndex );
   end;
..

"YIKES" i hear you say, "do i have to do this kind of gyrations for each array type i might need???". Well, you could, but it is not very difficult to write a set of generic procedures that will work for every base type you might use for an array. We assume that the array type is always declared with a lower bound of 0 and also use Cardinal instead of Word so the procedures will automagically expand to handle > 64K arrays under Delphi32.

 Procedure AllocArray( Var pArr: Pointer; items, itemsize: Cardinal;
                       Var maxIndex: Cardinal);
   Begin
     If items > 0 Then Begin
       GetMem( pArr, items * itemsize);
       maxIndex := Pred( items );
     End
     Else Begin
       pArr := Nil;
       maxIndex := 0;  { WARNING! This is still an invalid index here! }
     End;
   End;

 Procedure ReDimArray( Var pArr: Pointer; newItems, itemsize: Cardinal;
                       Var maxIndex: Cardinal );
   Begin
     If pArr = Nil Then
       AllocArray( pArr, newItems, itemsize, maxIndex )
     Else Begin
       ReAllocMem( pArr, Succ(maxIndex)*itemsize,
                   newItems*itemsize);
       maxIndex := Pred( newItems );
     End;
   End;

 Procedure DisposeArray( Var pArr: Pointer; itemsize, maxIndex: Cardinal );
   Begin
     FreeMem( pArr, Succ(maxIndex)*itemsize);
   End;

To use these procedures to make a dynamic array of Double, for example, you would proceed as follows:

  type
    {we can directly declare a pointer to an array, no need to declare
     the array first}
    PDoubleArray = ^Array [0..High(Cardinal) div Sizeof(Double) -1] of
                    Double;

  Var
    pDbl: PDoubleArray;
    maxIndex, i: Cardinal;
    deg2arc: Double;

  Begin
    deg2arc := Pi/180.0;
    try
      AllocArray( pDbl, 360, Sizeof( Double ), maxIndex );
      For i:= 0 To maxIndex Do
        pDbl^[i] := Sin( Float(i) * deg2arc );
      ReDimArray( pDlb, 720, Sizeof( Double ), maxIndex );
      For i:= 360 To maxIndex Do
        pDbl^[i] := Cos( Float(i-360) * deg2arc );
    finally
      DisposeArray( pDbl, Sizeof(Double), maxIndex );
    end;

And now the final icing: all this was typed off forehead; no idea if it will even compile <eg>! And a safety net feature is still missing: AllocArray and RedimArray should raise an exception if you try to allocate an array > 64Kbyte under Delphi16. I left this out since i'm not really familiar with these beasties (exceptions) yet. Delphi may do it anyway if range checking is enabled.

Here is Peter Below's approach:

time for my canned reply re. dynamic arrays:

You allocate your array on the heap with some incantations like

 Type
   TIntArray = Array [0..High(Word) div Sizeof(Integer) -1] of Integer;
   { declares the maximum size possible for an array of Integers }
   PIntArray = ^TIntArray;

 Procedure AllocArray( Var pArr: PIntArray; items: Word;
                       Var maxIndex: Word);
   Begin
     If items > 0 Then Begin
       GetMem( pArr, items * Sizeof( Integer ));
       maxIndex := Pred( items );
     End
     Else
       pArr := Nil;
   End;

 Procedure ReDimArray( Var pArr: PIntArray; newItems: Word;
                       Var maxIndex: Word );
   Begin
     If pArr = Nil Then
       AllocArray( pArr, newItems, maxIndex )
     Else Begin
       ReAllocMem( pArr, Succ(maxIndex)*Sizeof(Integer),
                   newItems*Sizeof(Integer));
       maxIndex := Pred( newItems );
     End;
   End;

 Procedure DisposeArray( Var pArr: PIntArray; maxIndex: Word );
   Begin
     FreeMem( pArr, Succ(maxIndex)*SizeOf(Integer));
   End;

 Var
  pMyArray: PIntArray;
  maxIndex, i: Word;

 Begin
   try
     AllocArray( pMyArray, 100, maxIndex );
     For i:= 0 To maxIndex Do
       pMyArray^[i] := i;
     ...
     RedimArray( pMyArray, 200, maxIndex );
     For i:= 0 To maxIndex div 2 Do
       pMyArray^[Succ(maxIndex div 2)+i] := Sqr(pMyArray^[i]);
     ....
   finally
   end;

"YIKES" I hear you say, "do I have to do this kind of gyrations for each array type i might need???". Well, you could, but it is not very difficult to write a set of generic procedures that will work for every base type you might use for an array. We assume that the array type is always declared with a lower bound of 0 and also use Cardinal instead of Word so the procedures will automagically expand to handle > 64K arrays under Delphi32.

 Procedure AllocArray( Var pArr: Pointer; items, itemsize): Card