Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to create dynamic arrays of records?

2,042 views
Skip to first unread message

Dave Brown

unread,
Dec 18, 1997, 3:00:00 AM12/18/97
to

This question is so simple that the title says it all. How do I create
arrays on the heap at run-time without knowing the size of the array at
compile time? Is there a way to reference the elements in a standard
array-like fashion rather than calculating the byte offset into the
array space? All of the examples that I see in books define a type of a
array of an array of a certain static size then allocate space for such
a type with a pointer to that type set to the allocated space. This
requires compile time knowledge of the array size. I need to declare
the size at run-time and be able to allocate and deallocate many arrays
of types or records or two dimensioned arrays.

Thanks for any responses

Dave Brown
Beaverton OR


Dave Brown

unread,
Dec 18, 1997, 3:00:00 AM12/18/97
to

Dave Brown

unread,
Dec 18, 1997, 3:00:00 AM12/18/97
to

David A. Schweizer

unread,
Dec 19, 1997, 3:00:00 AM12/19/97
to

The trick is to declare an array type of a certain static size, but
then to allocate only part of it:
type
TMyRecord =
record
{... }
end;

const
MaxSize = $fff0 div sizeof(TMyRecord);
{ maximum size for 16-bitDelphi }

type
PMyArray = ^TMyArray;
TMyArray = array[0..MaxSize - 1] of TMyRecord;

var
MyArrayPtr: PMyArray;

begin
{ dynamically allocate an array, 0 < SomeNumber <= MaxSize }
GetMem(MyArrayPtr, SomeNumber * sizeof(TMyRecord));
{ now you have an actual array of SomeNumber elements; note that YOU
have to do the range checking, the compiler will think there are
MaxSize elements! }

{ using the array: }
MyArrayPtr^[12] := SomeVariable;
SomeVariable := MyArrayPtr^[3]

{ deallocating }
FreeMem(MyArrayPtr, SomeNumber * sizeof(TMyRecord));
{ the last parameter can be left out in Delphi 2+ }

end.

This is the basic trick. For two-dimensional arrays, you would have to
use an array of pointers (e.g. PMyArray types) for the first
dimension. Hope you can deduce it from here.

hth
David
------------------
David A. Schweizer

iec ProGAMMA, The Netherlands
d.a.schweizer[OK, i don't want any more spam]gamma.rug.nl
guess where the '@' goes ?

Robert Lee

unread,
Dec 19, 1997, 3:00:00 AM12/19/97
to


David A. Schweizer wrote:

>
> The trick is to declare an array type of a certain static size, but
> then to allocate only part of it:
> type
> TMyRecord =
> record
> {... }
> end;
>
> const
> MaxSize = $fff0 div sizeof(TMyRecord);
> { maximum size for 16-bitDelphi }
>
> type
> PMyArray = ^TMyArray;
> TMyArray = array[0..MaxSize - 1] of TMyRecord;
>

Personally, I prefer to define the array as:

TMyArray = array[0..0] of TMyRecord;

and turn off range checking on the compiler options page. The eliminates the
potential for ambiguity on the actual size of the array. For instance,
high(MyArray^) = MaxSize in the original which might look plausable, whereas
my def yields 0 which is clearly wrong.

Bob Lee


Dave Shapiro

unread,
Dec 19, 1997, 3:00:00 AM12/19/97
to Da...@brown.org

Dave Brown wrote:
>
> This question is so simple that the title says it all. How do I create
> arrays on the heap at run-time without knowing the size of the array at
> compile time? Is there a way to reference the elements in a standard
> array-like fashion rather than calculating the byte offset into the
> array space? All of the examples that I see in books define a type of a
> array of an array of a certain static size then allocate space for such
> a type with a pointer to that type set to the allocated space. This
> requires compile time knowledge of the array size. I need to declare
> the size at run-time and be able to allocate and deallocate many arrays
> of types or records or two dimensioned arrays.
>
> Thanks for any responses

I can't stand the examples that declare an array of a static size ('That
should be large enough.') at compile time. It's ducking the issue.

Delphi isn't very nice about pointer arithmetic, but a good wrapper
class can hide all the details. I haven't had any speed problems with my
class.

I have a TDoublePointArray class which automatically allocates
TDoublePoint records as defined below:

type
TDoublePoint = record
X, Y: Double;
end;

It has an indexed Points[] property that returns any point in the array.
Is that what you want?

Give me an email and I'll send you the source. It even works in (*gasp*)
16-bit Windows using the global heap.

Cheers,

Dave
da...@cfxc.com

Peter N Roth

unread,
Dec 19, 1997, 3:00:00 AM12/19/97
to

Dave Brown wrote in message <67d7cj$k...@bgtnsc03.worldnet.att.net>...

>This question is so simple that the title says it all. How do I create
>arrays on the heap at run-time without knowing the size of the array at
>compile time?

The easiest answer: use the built-in TList.

For matrices & the like, check out our Matrix Math Toolkit
at our site...
--
Grace + Peace | Peter N Roth | Engineering Objects Int'l
Author: "Creating a Robust Type-Safe TList", Delphi Developer Oct 97
Visit our website at http://www.inconresearch.com/eoi
"On the internet, nobody knows you're a dog." - P Steiner


Enrique Polo

unread,
Dec 19, 1997, 3:00:00 AM12/19/97
to

The answer is as simple as the question:

Look in your Delphi Help file for the following topics:

varArrayCreate function { This allows you to create a variant size
array of any size }


varArrayReDim function { This allows you to resize a previously created
variant array }

The beauty is, since they are functions that return pointers to a variant
type, you can pass it the arguments as variables. Hence, run-time definable
arrays!!!! AN EXAMPLE:

procedure VarArrayExample;
var
Arr1 : Variant;
NumFields : Integer;
begin
NumFields := 10;
Arr1 := VarArrayCreate( [0, NumFields], varVariant );

NumFields := 100;
VarArrayReDim( Arr1, NumFields );
end;

Dave Brown wrote in message <67d7cj$k...@bgtnsc03.worldnet.att.net>...
>This question is so simple that the title says it all. How do I create
>arrays on the heap at run-time without knowing the size of the array at

>compile time? Is there a way to reference the elements in a standard
>array-like fashion rather than calculating the byte offset into the
>array space? All of the examples that I see in books define a type of a
>array of an array of a certain static size then allocate space for such
>a type with a pointer to that type set to the allocated space. This
>requires compile time knowledge of the array size. I need to declare
>the size at run-time and be able to allocate and deallocate many arrays
>of types or records or two dimensioned arrays.
>
>Thanks for any responses
>

>Dave Brown
>Beaverton OR
>

Peter N Roth

unread,
Dec 19, 1997, 3:00:00 AM12/19/97
to

Enrique Polo wrote in message <67eknv$8...@nrtphc11.bnr.ca>...

>The answer is as simple as the question:
>
>Look in your Delphi Help file for the following topics:
>
> varArrayCreate function { This allows you to create a variant size
>array of any size }
>
>
> varArrayReDim function { This allows you to resize a previously
created
>variant array }
>
>The beauty is, since they are functions that return pointers to a variant
>type, you can pass it the arguments as variables. Hence, run-time
definable
>arrays!!!! AN EXAMPLE:

I recommend NOT using varArray. They are mainly for
"interface compatibility", and trade away type-safety
for slower code. Better to use a TList or a derivative thereof.

Ashok Thirumurthi

unread,
Dec 23, 1997, 3:00:00 AM12/23/97
to Da...@brown.org

How about an array of a union of pointers that are allocated as needed. The
pointers can be arrays. The standard C++ solution is based on overloading
the array index operator. A metaclass that manages arrays of arrays uses
the same technique so a [][] calls minor * major::operator [] and datatype
minor::operator [] is called subsequently.

Ashok Thirumurthi
73060...@compuserve.com

Sundial Services

unread,
Dec 24, 1997, 3:00:00 AM12/24/97
to

> Ashok Thirumurthi
> 73060...@compuserve.com

>Dave Brown wrote:


What you should do in Delphi, Dave, is to set up (or buy or download) a
container class that will support a multidimensional array. Each of the
records is a separate object, and the container-class provides access to them.

For example, the SysTools package (Turbopower Software) provides about four
different types of large-matrix containers. You can also construct one of
your own.

For example, one class that I built, using SysTools to provide the underlying
support, accepts a list of arguments as a parameter, then hashes this into a
key that's used to look up the entry in a hash-dictionary. This was done for
an application with a very sparse matrix.

Notice that the container-class presents the *behavior* of an array without
necessarily using a contiguous block of memory -- even of pointers -- to do
it. The caller doesn't know or care how the class works.

And notice also that I referred, twice, to buying or downloading something
that already existed -- instead of "rolling your own." There's just so much
good stuff out there now that's either free or that costs the same as two
hours of your development time. :-/


Mike Powell

unread,
Dec 24, 1997, 3:00:00 AM12/24/97
to

Sundial Services wrote:

> >> This question is so simple that the title says it all. How do I create
> >> arrays on the heap at run-time without knowing the size of the array at
> >> compile time? Is there a way to reference the elements in a standard
> >> array-like fashion rather than calculating the byte offset into the
> >> array space? All of the examples that I see in books define a type of a
> >> array of an array of a certain static size then allocate space for such
> >> a type with a pointer to that type set to the allocated space. This
> >> requires compile time knowledge of the array size. I need to declare
> >> the size at run-time and be able to allocate and deallocate many arrays
> >> of types or records or two dimensioned arrays.
>
> What you should do in Delphi, Dave, is to set up (or buy or download) a
> container class that will support a multidimensional array. Each of the
> records is a separate object, and the container-class provides access to them.

If you are comfortable with the Delphi VCL then maybe a solution would
be to
"wrap" (or just use "as is") the TList. TLists are very good at storing
generic pointers to data. I use them all the time. It sure beats having
to
come up with another container or reinvent the wheel as it were.

0 new messages