User Tools

Site Tools


variable_length_array_structure

Variable-length array in a structure

by Richard Russell, September 2023

Suppose you're using a structure to represent an object, and a collection of those structures (perhaps a linked-list or a structure array) to represent a set of those objects. Further suppose that the objects themselves each contain a collection of things, which you want to represent as an array inside the structure.

All perfectly straightforward, because structures can contain arrays as members. But what if the collections within those objects are not all the same size, and indeed the size of the array is not known at the start? Now you're in trouble because an array structure-member has to be declared when the structure is created, so each of the objects ends up with the same size array:

DIM object{array(SIZE), other, structure, members}
DIM set_of_objects{(HOWMANY)} = object{}

The only obvious way to deal with this is to make the array the maximum size it can ever be, and to store the actual number of elements as another structure member:

DIM object{array(MAX_SIZE), actual_size%, other, structure, members}
DIM set_of_objects{(HOWMANY)} = object{}

But this is potentially very wasteful. If most of the objects contain only small collections (or perhaps no collection at all) and only a few contain large collections, you may have to allocate hugely more memory for the arrays than you really need to.

For a long time I couldn't think of an elegant solution to this, but there is one: rather than storing the array itself in the structure store a pointer to the array instead:

DIM object{array%%, other, structure, members}
DIM set_of_objects{(HOWMANY)} = object{}

With the aid of some helper routines you can now create and access different-sized arrays in each structure:

DEF PROC_create_array(object{}, size%)
PRIVATE temp()
PTR(temp()) = object.array%%
DIM temp(size%)
object.array%% = PTR(temp())
ENDPROC
DEF PROC_write_to_array(obkect{}, index%, number)
PRIVATE temp()
PTR(temp()) = object.array%%
temp(index%) = number
ENDPROC
DEF FN_read_from_array(object{}, index%)
PRIVATE temp()
PTR(temp()) = object.array%%
= temp(index%)

Using PRIVATE rather than LOCAL avoids any issues that might arise from BASIC expecting the 'temporary' array to be stored on the stack.

A potentially valuable side-effect is that the 'temporary' array, being a conventional array, can have functions like SUM() and MOD() applied which an array within a structure can't: CODE: SELECT ALL

DEF FN_sum_array(object{})
PRIVATE temp()
PTR(temp()) = object.array%%
= SUM(temp())
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
variable_length_array_structure.txt · Last modified: 2024/01/05 00:21 by 127.0.0.1