=====Deconstructing arrays=====
//by Jon Ripley, August 2006//\\ \\ This article assumes that you have read the manual section [[http://www.bbcbasic.co.uk/bbcwin/manual/bbcwind.html#arrays|'Array storage in memory']]. This article expands on the documentation and shows how to use this information in a real program.\\ \\ Understanding the layout and structure of arrays in memory has practical applications when dealing with arrays from assembly language and when writing code that manipulates arrays. This information can also be used to implement methods to deal with arrays in ways not natively supported by BBC BASIC.\\ \\
==== Reading the array pointer ====
\\ The most important part of an array is the pointer to the array data block and reading this is the first step in deconstructing an array. But we also need an array to deal with and one such example is created below.\\ \\
DIM array(1, 2, 3, 4)
parr% = ^array():REM Pointer to array
\\ Here we dimension an example array **array()** and set **parr%** to the pointer to this array.\\ \\
==== Basic array information ====
\\
PRINT "Pointer to parameter block address: &";~parr%
PRINT "Address of parameter block: &";~!parr%
PRINT "Number of dimensions: ";?!parr%
PRINT "Address of data area: &";!parr%+1+?!parr%*4
\\ Here we display basic information about the array. The pointer to the parameter block could be expressed as **^array()**, the parameter block address could be expressed as **!^array()** and the number of dimensions could be expressed as **?!^array()**.\\ \\ **Note:** The following code could be rewritten with **^array()** replacing each instance of **parr%** but this would limit us to only examining an array called **array()**. By storing the pointer to the array in **parr%** we can use this code to examine any type of array.\\ \\
==== Reading the size of each dimension ====
\\ To find the size of each dimension in the array and calculate the total number of elements in the array use the following code:\\ \\
tele% = 1:REM Total number of elements
FOR i% = 0 TO ?!parr% - 1
nele% = !(!parr%+1+4*i%)
PRINT "Size of dimension #";i%": ";nele%-1" + 1"
tele% *= nele%
NEXT i%
PRINT "Total number of elements: ";tele%
\\ Here we iterate through the dimensions of the array and read the number of elements in each dimension (**nele%**) and display the result. The running total number of elements in the array is calculated and stored in **tele%**, this value is used to calculate the size of the array data block.\\ \\
==== Determining the array type ====
\\ Arrays can contain different types of variable and each variable type occupies a different number of bytes in memory. Knowing the type of an array is important when manipulating the data in the array or the array itself. The array variable name is precedes the array pointer in memory. This allows us to find the type of variable stored in the array. The variable type is stored three bytes before the array pointer.\\ \\ We can use this information to find the type of variable stored in the array:\\ \\
PRINT "Array type: ";
CASE parr%?-3 OF
WHEN ASC"%": PRINT "Integer": esize%=4
WHEN ASC"#": PRINT "Double": esize%=8
WHEN ASC"$": PRINT "String": esize%=6
WHEN ASC"&": PRINT "Byte": esize%=1
OTHERWISE: PRINT "Single": esize%=5
ENDCASE
PRINT "Size of each element: ";esize%" bytes"
\\ Here **esize%** is set to the size in bytes of the variable type stored in the array. One variable type, the 40-bit real, does not have a type suffix so it is possible to assume that any variable name that does not end in **%**, **#**, **$** or **&** is a 40-bit real. When BBC BASIC is in //float 64// mode all new real variables have the **#** suffix silently added to the end of the name. This is essential for BBC BASIC to tell the difference between the two types of real variable.\\ \\ **Note:** We are ignoring structures and arrays here as these variable types cannot be contained within an array. Structure variable names have a '**{**' suffix and array variable names have a '**(**' suffix.\\ \\
==== Calculating the total size of the array ====
\\ The total size of the array data area equals the total number of elements (**tele%**) multiplied by the size of each element (**esize%**). The total size of the array block equals the size of the data area plus one byte for the number of dimensions and four extra bytes for the description of each dimension.\\ \\ We can now use all the information collected so far to determine the total size of the array in memory:\\ \\
PRINT "Total data area size: ";tele%*esize%" bytes"
PRINT "Total array size: ";1+4*?!parr%+tele%*esize%" bytes"
\\
==== How to verify the array pointer ====
\\ When writing code that manipulates arrays by reference it is a good idea to check that the array pointer **parr%** is actually a pointer to an array. Not doing so will lead to undefined behaviour and may crash //BBC BASIC// if your code is called with an invalid array pointer.\\ \\ To check if a pointer points to an array use the following code:\\ \\
IF NOT (parr%?-1 = 0 AND parr%?-2 = 40) THEN
REM parr% does not point to an array
ELSE
REM parr% points to an array
ENDIF
\\ Here we check for a variable descriptor that matches an array. If the array pointer **parr%** does not point to a valid array block the routine should not attempt to access or manipulate data in the invalid array.