Arrays

Multi-dimensional container types.

Overview
   Arrays are special kinds of variables which act as containers for a 
   number of values, or elements. An array can store elements of any type, 
   and all of its elements share the same type. For example, an array can 
   store Integer elements or Single elements, but not both. These elements 
   are accessed--read from or written to--through an Integer value 
   representing their position in the array. Arrays have lengths, or sizes, 
   which are equal to the number of elements they are storing at any given 
   time. Fixed-length arrays have constant sizes throughout their 
   lifetimes, while the sizes of variable-length arrays can change 
   dynamically.

Elements and positions
   The values that an array stores are its elements. Each element of an 
   array has a corresponding position, which is an Integer value ranging 
   from the array's lower bound to its upper bound, inclusive. These 
   positions are used to access individual elements in the array using 
   Operator (), which takes a position and returns a reference to the 
   element at that position. A valid position in an array is greater than 
   or equal to its lower bound, and less than or equal to its upper bound.
   ' Create an array of 3 elements all having the value zero (0.0f).
   Dim array(1 To 3) As Single

   ' Assign a value to the first element.
   array(1) = 1.2

   ' Output the values of all the elements ("1.2 0 0").
   For position As Integer = 1 To 3
      Print array(position)
   Next
      

Sizes and bounds
   The size of an array is equal to the number of elements it stores at any 
   given time. An array can have a size of zero (0), meaning it's not 
   storing any values at the moment--it's empty. If an array's size is 
   greater than zero, that many elements are being stored. An array's size 
   is equal to one more than the difference between its upper and lower 
   bounds, or UBound(array) - LBound(array) + 1.

   The lower and upper bounds not only determine the size of an array, but 
   also the valid positions of individual elements. For example, an array 
   with a lower bound of zero (0) and an upper bound of four (4), stores 
   five (5) elements, the first element being at position 0, the last at 
   position 4. These bounds may be specified when the array is declared, 
   or, for some arrays, changed by resizing the array. An array's lower and 
   upper bounds can be retrieved using LBound and UBound, respectively.

   When creating or resizing an array, if a lower bound is not specified it 
   defaults to zero (0).
   ' Declares and initializes an array of four integer elements.
   Dim array(3) As Integer = { 10, 20, 30, 40 }

   ' Outputs all of the element values (" 10 20 30 40").
   For position As Integer = LBound(array) To UBound(array)
      Print array(position) ;
   Next
      

Fixed-length and variable-length
   There are two fundamental kinds of arrays: fixed-length and 
   variable-length. The primary difference between the two is that the 
   bounds of fixed-length arrays can never change, that is, they always 
   store the same number of elements in the same positions. Variable-length 
   array bounds can be changed, affecting the number of elements stored 
   and/or the positions of the elements.

   Since fixed-length arrays never change size, the compiler chooses to 
   make room for--or, allocate--the memory for the array elements either in 
   static storage or on the program stack, depending on the array's 
   storage class. This can be an advantage, since the cost of creating 
   these kinds of arrays doesn't include any adverse run-time penalty. 
   Fixed-length arrays are declared using Extern, Static and Dim. At least 
   an upper bound must be specified, and all bounds must be compile-time 
   constant values, such as numeric literals, Const variables or Enum 
   enumerators.

   Variable-length arrays can change in size, so the compiler chooses to 
   allocate the memory for the array elements at run-time, in the free 
   store. The advantage here of course is being able to dynamically resize 
   the arrays, however, run-time performance could vary when they are 
   created, resized or destroyed. Variable-length arrays are declared using 
   Extern, Static, Dim and ReDim. When using Extern, Static or Dim, the 
   lower and upper bounds can be left unspecified--resulting in an empty 
   array--or either one must have a variable value, such as an Integer 
   variable or Function result. ReDim can be used to resize an existing 
   variable-length array, by giving it different lower and/or upper bounds.
   ' Creates a fixed-length array that holds 5 single elements.
   Const totalSingles = 5
   Dim flarray(1 To totalSingles) As Single

   ' Creates an empty variable-length array that holds integer values.
   Dim vlarray() As Integer

   ' Resizes the array to 10 elements.
   ReDim vlarray(1 To 10)
      

Multi-dimensional arrays
   The arrays discussed so far have been one-dimensional, that is, the 
   elements are accessed through a single position. One-dimensional arrays 
   can be thought of as a simple row of elements. Arrays can also have more 
   than one dimension; an individual element of the array is accessed using 
   two or more positions. Two-dimensional arrays use two positions--a row 
   and a column position--to refer to individual elements, like a grid or 
   table. Three-dimensional arrays use three positions--a row, column and 
   perhaps depth position--to refer to individual elements, like a cube. 
   Four-dimensional arrays can be thought of as one or more 
   three-dimensional arrays, and so on. Multi-dimensional arrays are 
   declared just like one-dimensional arrays, except that more than one 
   lower and upper bound range is specified.
   The total number of elements and the total size (in bytes) of a 
   multi-dimensional array can be directly obtained using Arraylen and 
   Arraysize, respectively.
   ' Take Care while initializing multi-dimensional array
   Dim As Integer multidim(1 To 2,1 To 5) = {{0,0,0,0,0},{0,0,0,0,0}}
      

Detailed use of LBound and UBound
   LBound / UBound returns the lower / upper values of size information for 
   an array: the dimension of the array (number of usable indexes) and the 
   index bounds for each dimension. The array name is specified in the 
   first parameter, and the dimension selection in the second parameter.
   These sizing information are available both for a fixed-length array 
   (sizing fixed at compile-time) and for a variable-length array (some 
   sizing adjustable during run-time).

   - Usage:
      result = (L|U)Bound( array [, dimension ] )
         with as parameters:
            array : array name, without parentheses
            dimension : dimension number to get the bound, ordered from 
            left to right compared to index position when accessing array
               (1 = first dimension)

   - Return value:
      For the specific dimension value '0':
         LBound returns always '1', and UBound returns the number of 
         dimensions
            if the array is not fully sized (declared as 'array( )' or 
            'array( Any [, Any...] )'), UBound returns '0'

      For any valid dimension value of the array (from 1 to the last one):
         (L|U)Bound returns the lowest|highest value that can be used as an 
         index for the specified dimension
            if the array is not fully sized (declared as 'array( )' or 
            'array( Any [, Any...] )'), LBound returns '0' and UBound 
            returns '-1'

      For any other dimension value (dimension number not relevant):
         LBound returns always '0', and UBound returns always '-1'

      Summarizing table example:

   Array definition |      array( )       | array( Any , Any )  | array( 4 , 5 To 9 ) |
   Dimension nb (x) |                     |        (1)   (2)    |       (1)    (2)    |
   -----------------|---------------------|---------------------|---------------------|
   LBound(array, 0) |      1              |      1              |      1              |
   UBound(array, 0) |      0              |      0 (but Not 2!) |      2              |
   -----------------|---------------------|---------------------|---------------------|
   LBound(array, 1) |      0              |      0              |      0 (by default) |
   UBound(array, 1) |     -1              |     -1              |      4              |
   -----------------|---------------------|---------------------|---------------------|
   LBound(array, 2) |      0              |      0              |      5              |
   UBound(array, 2) |     -1              |     -1              |      9              |
   -----------------|---------------------|---------------------|---------------------|
   LBound(array, k) |      0              |      0              |      0              |
   UBound(array, k) |     -1              |     -1              |     -1              |
     For k<0 Or k>2 |                     |                     |                     |
   -----------------|---------------------|---------------------|---------------------|
   			

   - Use cases:
      So UBound( array , 0 ) value allows to easily determine if an array 
      is sized (value > 0) or not (value = 0), and if yes the number of 
      dimensions (the positive value).
         Remark: ( ( LBound( array ) = 0 ) AND ( UBound( array ) = -1 ) ) 
         Or ( @array( LBound( array ) ) = 0 ) would allow to only know that 
         the array is un-sized.

      Once the number of dimensions is determined, the information on the 
      two boundaries of each dimension is safely accessible.

      Example of a macro that displays all the sizing information for an 
      array:
   #macro PRINT_ARRAY_SIZING (array)
      If UBound( array , 0 ) = 0 Then
         Print "'" & #array & "' un-sized"
      Else
         Print "'" & #array & "' sized with " & UBound( array , 0 ) & " dimension";
         If UBound( array , 0 ) > 1 Then
            Print "s";
         End If
         Print
         For I As Integer = 1 To UBound( array , 0 )
            Print "   dimension nb: " & I
            Print "      lower bound: " & LBound( array , I )
            Print "      upper bound: " & UBound( array , I )
         Next I
      End If
   #endmacro

   Dim As Integer array1( )
   PRINT_ARRAY_SIZING( array1 )
   Print

   Dim As Single array2( Any )
   PRINT_ARRAY_SIZING( array2 )
   Print

   Dim As String array3( 4 , 5 To 9 )
   PRINT_ARRAY_SIZING( array3 )
   Print

   Type UDT
      Dim As Double array4( Any, Any, Any )
   End Type

   Dim As UDT u
   PRINT_ARRAY_SIZING( u.array4 )
   Print

   ReDim u.array4( -7 To -3, -2 To 5, 6 To 9 )
   PRINT_ARRAY_SIZING( u.array4 )
   Print

   Erase u.array4
   PRINT_ARRAY_SIZING( u.array4 )
   Print

   Sleep
            
Output:

   'array1' un-sized

   'array2' un-sized

   'array3' sized with 2 dimensions
      dimension nb: 1
   	  lower bound: 0
   	  upper bound: 4
      dimension nb: 2
   	  lower bound: 5
   	  upper bound: 9

   'u.array4' un-sized

   'u.array4' sized with 3 dimensions
      dimension nb: 1
   	  lower bound: -7
   	  upper bound: -3
      dimension nb: 2
   	  lower bound: -2
   	  upper bound: 5
      dimension nb: 3
   	  lower bound: 6
   	  upper bound: 9

   'u.array4' un-sized
   				

   - Notes:
      The maximum number of dimensions of a multidimensional array is 8.

      At the contrary to QB, FB stores the multidimensional arrays data in 
      this definite order: values differing only in the last index are 
      contiguous in memory (row-major order).

      An array declared with 'Any' instead of the bound fields is 
      considered presently to be fully un-sized from UBound ('UBound( array 
      , 0 ) = 0'), while at least its number of dimensions is already fixed 
      (and locked).
      Moreover this value of the number of dimensions is well set in the 
      array descriptor.
      In this case, UBound( array , 0 ) could return this value while 
      remaining with LBound (array , 0 ) = 0 and UBound( array , 0 ) = -1.
      A bug report (#853) has been filled in, about this behavior.

See also
   * Fixed-length Arrays
   * Variable-length Arrays
   * Array Indexing
   * Passing Arrays to Procedures
   * Variable Scope

