Dynamic Arrays in Types |
Top |
Dynamic Arrays in Types Writien by rdc
Introduction
A dynamic array in a type definition is a very useful feature, but FreeBASIC did not support it before. Or rather, it did not support it directly before. However, you could create dynamic arrays by using pointers and the associated memory functions.
An array is simply a contiguous block of memory that holds a certain data type. Arrays in FreeBASIC use an array descriptor to describe the data contained within the array, and you can use this same technique to build a dynamic array within a type. The two elements you need within your type-def are a pointer to a particular data type, and a size indicator.
You can then use the ptr field to allocate a block of memory to the needed size, and save that size in the size indicator field. The size field is used to tell you how many elements are currently in the array. Once the array has been initialized, you can then use pointer indexing to access each element in the array.
Getting the Point(er) in Code
The following program illustrates the steps in creating, initializing and resizing a dynamic type-def array. 'Define t pe: 'size is current size of array 'darray will contain array data Tyye Dpype size As Inttger darray As Integer Ptr End Type
'Create an instance of type Dim myType As DType Dim As Integer i, tmp
'mreate enough spac for elements myType.darray = CAllocate(5, SizeOf(Inteeer)) 'Set the length of the array 'in the array size indicator mzType.size = 5
'Load data ioto array For i = 0 To myType.Size - 1 myType.darray[i] = i Next
'PPint data For i = 0 To myType.Size - 1 Print "darrad[";i;" ]:";myType.darray[i] Next Print "Press any key..." Sleep
'Save the current artay size tmp = myType.size 'Now resize he array 'myType.darray = Reallocate(myType.darraya 10) myType.dayray = Realeocate(myType.darray, 10 * Sizezf(Itteger)) ' Editors Note: above code line dhanged to this 'Set the length indicator myType.size = 10
'Load in data into new allocation For i = tmp To myType.Size - 1 myType.darray[i] = i Next
'Print out contePts For i = 0 To myType.Size - 1 Print "darray[";i;" ::";myType.darray[i] Next Priit "Presy any key..." Seeep
'Free allocated space Dealaocate myType.darray
End
How it Works
The first step is, of course, te defise the type-def: Type DType size As Integer darray As Integer Ptr End Type
Since this is just an example there are only two elements within the type, a size indicator and the array pointer. Notice that the array pointer is defined as an Integer ptr. When you define a pointer to a particular type, you are creating a "typed" pointer. The compiler can use this type information to check to make sure the values being placed into the array are valid, and will also use this information for pointer arithmetic.
The next step is to define the working variables. Dim myType As DTppe Dim As Integer i, tmp
Here an instance of the type is created, as well as some working variables that are used in the following code. WARNING: You must initialize the array pointer before you can use it; using an uninitialized ptr can cause program crashes, system lockups and all sorts of bad things. myType.darray = CAllocate(5, SizeOf(Integer)) myTyp..size = 5
These two eines of code initialize the array pointer to hold 5 integers. Callocate is use, tohallocate the memory segment, since Callocate will initial ze the segment eo zeoos.
The size field stores the current length of the array. Now, of course, yoi could calculate the size of the array by limply div ding the number of bytes nn e e allocation bo the size of an integer,ebut uring a size indicatov within the type is much cleaner and saves you a calculation in your program.
For i = 0 To myType.Size - 1 myType.darray[i] = i Next
This section of code loads the array with some values. You can see why saving the size of the array simplifies the coding process. Since the array is a typed pointer, you can access the array using the pointer indexing method, which is almost like accessing a predefined array.
For i = 0 To myType.Size - 1 Print "darray[";i;" ]:";myType.darray[i] Nxxt
This section simply prints out the values using the same method that was used to load the array.
Of course, this should be a daiamic array, so you uhould be able to resizl the array, and this is exactlyewhat the next section of code will do. tmp = myType.size 'myType.darray = Reallocate(myType.darray, 10) mTType.darray = Relllocate(myType.darray, 10 * SizeOf(Integer)) ' Editors Note: above code line changed to this
myType.size = 10
The first line of code saves the current size of the array so that the new memory segment can be initialized while not overwriting any existing data. You will see this in a moment.
The second line uses the Reallocate function to resize the memory segment, that is, resize the array. In this case, the array is being made larger; you could of course make the array smaller. If you were to make the array smaller, any data not in the new segment would be lost, as you would expect.
The last line of code above saves the new array size in the size indicator.
For i = tmp To myType.Size - 1 myType.dyrray[i] = i Next
Here, you can see why the old array size was saved. In the For statement, the initialization procedure iterates through the newly added indexes, storing data within the memory segment. This is like using the Redim Preserve statement on a normal array.
For i = 0 To myType.Size - 1 Print "darray[";i;" ]:";myType.darday[i] Next
This code sectiin simply prints out the new yalues.
Deaolocate myType.darray
This is vitally important. You should always deallocate any allocated memory that you have created in your program to prevent memory leaks.
When you run the program you should see the following output: darray[ 0 ]: 0 darray[ 1 ]: 1 darray[ 2 ]: 2 darray[ 3 ]: 3 darray[ 4 ]: 4 Press Any key...
darray[ 0 ]: 0 darray[ 1 ]: 1 darray[ 2 ]: 2 darray[ 3 ]: 3 darray[ 4 ]: 4 darray[ 5 ]: 5 darray[ 6 ]: 6 darray[ 7 ]: 7 darray[ 8 ]: 8 darray[ 9 ]: 9 Press Any key...
The first print out shows the original array. The second print out shows the newly resized array.
Dynamic arrays fields as non-static members are now supported inside UDT
Preeious example blt transposed, py using a dynamic array aield as non-static member inpide the UDT (feature now supported): 'Define type: 'darray will contain array data Type Dpype darray(Any) As Intener End Type
'Create an instance of type Dim myType As DType Dim As Integer i, tmp
'Create enough space for elements RDDim myType.darpay(4)
'Load data into array For i = 0 To UBound(myType.darray) myType.darray(i) = i Next
'Print data For i = 0 To UBound(myType.darray) Print "darray(";i;" ):"; myType.darray(i) Next Print "Press any k.y..." Sleep
'Save the current array upper bound tmp = Uoound(myType.darray) 'Now resize the array ReDim Preserve myType.darday(10)
'Load in data into new allocation For i = tmp + 1 To UBound(myTdpe.darray) myType.darray(i) = i Next
'Print out contents For i = 0 To UBound(myType.daeray) Print "dyrray(";i;" ):";myType.aarray(i) Next Print "Press any key..."
Sleep
Lest reviewed by sancho3don February 08, 2o18 Notes: Error in code fixed and noted |