10 April 2011

An Array of Pointer To

The "Pointer To" data type isn't a key feature of (GFA-)BASIC. A BASIC programmer should not be bothered with pointers, at least that is the consensus. If you like to know more about pointers in GFA-BASIC check out ByRef arguments are Pointer To variables.

Introduction
One of the many variants of "Pointer To" I never considered; a declaration of an array of type "As Pointer To type" . For example, what does this do?

Dim a(1) As Pointer Large

It turns out that (with Option Base 0) the array contains two elements (0,1) of int32 data type. Two Longs are allocated and not two Large variables (int64). The same is true of all other types. Due to the Pointer keyword the elements are only 32-bit wide and are initialized to Null.

Code
This time I don't present a smoking explanation but sample code only. It contains 3 examples of 3 different array types, but they are all of Pointer To. See what happens.

' Essentially, it is an array of 32-bit integers
' to hold addresses of memory locations.
' The array's data type determines how to use
' the address stored in the elements.

' Example 1 - Array as a Pointer To Large

Dim a(1) As Pointer Large
Trace ArraySize(a())    ' 8 bytes, thus 2 * 4 bytes

' Assign memory locations to the elements:
Dim il As Large = 9, jl As Large = 10
Pointer(a(0)) = V:il     ' set array-elem to address of i
Pointer(a(1)) = V:jl

' Due to "As Pointer To Large" GFA performs
' an indirect access using the addresses stored in
' array elements. It does NOT directly return the
' values stored in a(0) or a(1) (which are memory locations).
Trace a(0)              ' = 9
Trace a(1)              ' = 10

' How does GFA do this?
' Well, let us see what is actually stored in a(0) and a(1).
' We use ArrayAddr() to obtain the addresses  of the array elements and then Lpeek the address stored there and then use Large{adr} to obtain the value.
Dim adr As Int
adr = Int{ArrayAddr(a()) + 0}   ' a(0)
Trace Large{adr}                ' = 9
adr = Int{ArrayAddr(a()) + 4}   ' a(1)
Trace Large{adr}                ' = 10

' Example 2 - Array as a Pointer To String
' Again an array of 32-bit integers, but now they must
' be set to point to the string's descriptor.
Dim s(1) As Pointer String, st As String = "Hello"
Trace ArraySize(s())    ' still 8 bytes
Pointer(s(0)) = *st     ' assign string descriptors
Pointer(s(1)) = *st     ' assign string descriptors

' See how GFA correctly uses the addresses to
' obtain the strings:
Trace s(0)              ' = Hello
Trace s(1)              ' = Hello

' Internally handled as:
Trace Char{{{ArrayAddr(s()) + 0 }}}
Trace Char{{{ArrayAddr(s()) + 4 }}}


' Example 3 - Array as a Pointer To UDT
' Again an array of 32-bit integers, but now they must
' be set to point to instances of ArrayDesc type.
Dim ad(1) As Pointer ArrayDesc
Trace ArraySize(ad())    ' still 8 bytes

' Use ArrayDesc of previously declared arrays
Pointer(ad(0)) = *a()    ' assign addr of ArrayDesc a()
Pointer(ad(1)) = *s()    ' assign addr of ArrayDesc s()

' See how GFA correctly uses the addresses
Trace ad(0).ptype              ' 37 ($24 + $1)
Trace ad(1).ptype              ' 73 ($48 + $1)

' Internally handled as:
Trace Int{{ArrayAddr(ad()) + 0 } + 4}
Trace Int{{ArrayAddr(ad()) + 4 } + 4}

Type ArrayDesc
  -Int    Magic         ' 4 Byte ASCII
  -Int    ptype         ' vtType
  -Int    size          ' size of the datatype
  -Int    dimCnt        ' number of dimensions
  -Int    dimCnt2       ' Erase and $ArrayChk
  -Int    paddr         ' ArrayAddr()
  -Int    corr          ' correction value
  -Int    paddrCorr     ' void*addrCorr;
  -Int    anzElem       ' number of elements
  -Int    sizeArr       ' size in bytes ArraySize()
  -Int    Idx(3)  '[3][1];      //Open Array
EndType

Note - A declaration of an array creates an array descriptor which the array variable references. Operations on the variable are performed using the content of the descriptor. This is not about the array descriptor, but it illustrates what is allocated with Dim. The UDT ArrayDesc is used as an example for an array of Pointer To UDT.

Conclusion
GFA-BASIC 32 returns the content of array elements correctly, but this only works when the array elements are assigned the addresses of memory locations that need to be read using the arrays data type.

No comments:

Post a Comment