Handling Arrays and Visual Fortran Array Descriptors

Fortran 95/90 allows arrays to be passed as array elements, as array subsections, or as whole arrays referenced by array name. Within Fortran, array elements are ordered in column-major order, meaning the subscripts of the lowest dimensions vary first.

When using arrays between Fortran and another language, differences in element indexing and ordering must be taken into account. You must reference the array elements individually and keep track of them. Fortran, Visual Basic, MASM and C vary in the way that array elements are indexed. Array indexing is a source-level consideration and involves no difference in the underlying data.

Visual Basic stores arrays and character strings as descriptors: data structures that contain array size and location. This storage difference is transparent to the user, however.

To pass an array from Visual Basic to Fortran, pass the first element of the array. By default, Visual Basic passes variables by reference, so passing the first element of the array will give Fortran the starting location of the array, just as Fortran expects. Visual Basic indexes the first array element as 0 by default, while Fortran by default indexes it as 1. Visual Basic indexing can be set to start with 1 using the statement:

  Option Base 1

Alternatively, in the array declaration in either language you can set the array lower bound to any integer in the range -32,768 to 32,767. For example:

 ' In Basic
 Declare Sub FORTARRAY Lib "fortarr.dll" (Barray as Single)
 DIM barray (1 to 3, 1 to 7) As Single
 Call FORTARRAY(barray (1,1))

 ! In Fortran
 Subroutine FORTARRAY(arr)
    REAL arr(3,7)

In MASM, arrays are one-dimensional and array elements must be referenced byte-by-byte. The assembler stores elements of the array consecutively in memory, with the first address referenced by the array name. You then access each element relative to the first, skipping the total number of bytes of the previous elements. For example:

 xarray    REAL4     1.1, 2.2, 3.3, 4.4 ; initializes
                       ; a four element array with
                       ; each element 4 bytes

Referencing xarray in MASM refers to the first element, the element containing 1.1. To refer to the second element, you must refer to the element 4 bytes beyond the first with xarray[4] or xarray+4. Similarly:

 yarray     BYTE      256 DUP     ; establishes a
                 ; 256 byte buffer, no initialization
 zarray SWORD 100 DUP(0) ; establishes 100
                 ; two-byte elements, initialized to 0

Fortran and C arrays differ in two ways:

In C, the first four elements of an array declared as X[3][3] are:

  X[0][0] X[0][1] X[0][2] X[1][0]

In Fortran, the first four elements are:

  X(1,1) X(2,1) X(3,1) X(1,2)

The order of indexing extends to any number of dimensions you declare. For example, the C declaration:

  int arr1[2][10][15][20];

is equivalent to the Fortran declaration:

  INTEGER arr1( 20, 15, 10, 2 )

The constants used in a C array declaration represent extents, not upper bounds as they do in other languages. Therefore, the last element in the C array declared as int arr[5][5] is arr[4][4], not arr[5][5].

The following table shows equivalencies for array declarations.

Equivalent Array Declarations for Different Languages

Language Array Declaration Array Reference from Fortran
Fortran DIMENSION x(i, k)
-or-
type x(i, k)
x(i, k)
Visual Basic DIM x(i, k) As type x( i -1, k -1)
Visual C/C++ type x[ k ] [ i ] x( i -1, k -1)
MASM Declare and reference arrays as elements in consecutive storage

Visual Fortran Array Descriptor Format

For cases where Fortran 95/90 needs to keep track of more than a pointer memory address, the Visual Fortran compiler uses an array descriptor, which stores the details of how an array is organized.

When using an explicit interface (by association or procedure interface block), Visual Fortran will generate a descriptor for the following types of array arguments:

Certain data structure arguments do not use a descriptor, even when an appropriate explicit interface is provided. For example, explicit-shape and assumed-size arrays do not use a descriptor. In contrast, array pointers and allocatable arrays use descriptors regardless of whether they are used as arguments.

When calling between Visual Fortran and a non-Fortran language (such as C), using an implicit interface allows the array argument to be passed without a Visual Fortran descriptor (see Passing Array Arguments Efficiently). However, for cases where the called routine needs the information in the Visual Fortran descriptor, declare the routine with an explicit interface and specify the dummy array as either an assumed-shape array or with the pointer attribute.

You can associate a Fortran 95/90 pointer with any piece of memory, organized in any way desired (so long as it is "rectangular" in terms of array bounds). You can also pass Fortran 95/90 pointers to other languages, such as C, and have the other language correctly interpret the descriptor to obtain the information it needs.

However, using array descriptors can increase the opportunity for errors and is not portable:

The components of the current Visual Fortran array descriptor on ia32 systems follow:

An array of rank one would require three additional longwords for a total of in eight longwords (5 + 3*1) and end at byte 31. An array of rank seven would be described in a total of 26 longwords (5 + 3*7) and end at byte 103.

For example, consider the following declaration:


   integer,target :: a(10,10)
   integer,pointer :: p(:,:)
   p => a(9:1:-2,1:9:3)
   call f(p)
   .
   .
   .

The descriptor for actual argument p would contain the following values:

For information about performance implications of passing different types of array arguments, see Passing Array Arguments Efficiently.