



Arrays as Arguments The simplest, and most common, requirement is to make the entire contents of an array available in a procedure. If the actual argument arrays are always going to be the same size then the dummy arrays in the procedure can use fixed bounds. For example:
SUBROUTINE DOT(X, Y, Z) *Computes the dot product of arrays X and Y of 100 elements * producing array Z of the same size. REAL X(100), Y(100), Z(100) DO 15, I = 1,100 Z(I) = X(I) * Y(I) 15 CONTINUE END |
PROGRAM PROD
REAL A(100), B(100), C(100)
READ(UNIT=*,FMT=*)A,B
CALL DOT(A, B, C)
WRITE(UNIT=*,FMT=*)C
END
|
A more satisfactory solution is to generalise the procedure so that it can be used on arrays of any size. This is done by using an adjustable arrays declaration. Here the operands in each dimension bound expression may include integer variables which are also arguments of the procedure (or members of a common block). The following example shows how this may be done:
SUBROUTINE DOTPRO(NPTS, X, Y, Z) REAL X(NPTS), Y(NPTS), Z(NPTS) DO 15, I = 1,NPTS * etc. |
CALL DOTPRO(100, A, B, C)
An adjustable array declaration is permitted only for arrays which are dummy
arguments, since the actual array space has in this case already been allocated in the
calling unit or at some higher level. The method can be extended in the obvious way
to cover multi-dimensional arrays and those with upper and lower bounds, for
example:
SUBROUTINE MULTI(MAP, K1, L1, K2, L2, TRACE) DOUBLE PRECISION MAP(K1:L1, K2:L2) REAL TRACE(L1-K1+1) |
Each array bound of a dummy argument array may be an integer expression involving not only constants but also integer variables passed in to the procedure either as arguments or by means of a common block. The extent of each dimension of the array must not be less than one and must not be greater than the extent of the corresponding dimension of the actual argument array.
If any integer variable (or named constant) used in an array-bound expression has
a name which does not imply integer type then the INTEGER statement which
specifies its type must precede its use in a dimension-bound expression.
There may be circumstances in which it is impracticable to use either fixed or adjustable array declarations in a procedure because the actual size of the array is unknown when the procedure starts executing. In this case an assumed-size array is a viable alternative. These are also only permitted for dummy argument arrays of procedures, but here the array is, effectively, declared to be of unknown or indefinite size. For example:
REAL FUNCTION ADDTWO(TABLE, ANGLE) REAL TABLE(*) N = MAX(1, NINT(SIN(ANGLE) * 500.0)) ADDTWO = TABLE(N) + TABLE(N+1) END |
An assumed size dummy argument array is specified with an asterisk as the upper bound of its last (or only) dimension. All the other dimension bounds, if any, must conform to normal rules for local arrays or adjustable arrays.
There is one important restriction on assumed size arrays: they cannot be used
without subscripts in I/O statements, for example in the input list of a READ
statement or the output list of a WRITE statement. This is because the compiler
has no information about the total size of the array when compiling the
procedure.
The rules of Fortran require that the extent of an array (in each dimension if it is multi-dimensional) must be at least as large in the actual argument as in the dummy argument, but they do not require actual agreement of both lower and upper bounds. For example:
PROGRAM CONFUS REAL X(-1:50), Y(10:1000) READ(UNIT=*,FMT=*) X, Y CALL OUTPUT(X) CALL OUTPUT(Y) END SUBROUTINE OUTPUT(ARRAY) REAL ARRAY(50) WRITE(UNIT=*,FMT=*) ARRAY END |
PROGRAM TWODIM REAL D(100,20) * ... NSLICE = 15 CALL OUTPUT(D(1,NSLICE)) |
The use of an array element as an actual argument when the dummy argument is a complete array is a very misleading notation and the transfer of array sections should be avoided if at all possible.
When a dummy argument is a character array the passed-length mechanism can be used in the same way as for a character variable. Every element of the dummy array has the length that was passed in from the actual argument.
For example, a subroutine designed to sort an array of character strings into ascending order might start with specification statements like these:
SUBROUTINE SORT(NELS, NAMES) INTEGER NELS CHARACTER NAMES(NELS)*(*) |
CHARACTER*80 LINE
could be passed to a subroutine which declared it as an array of four 20-character
elements:
SUBROUTINE SPLIT(LINE) CHARACTER LINE(4)*20 |