Arrays as arguments
Last updated on 2026-07-21 | Edit this page
Overview
Questions
- How are arrays passed as arguments?
- How are array slices passed as arguments?
- How do allocatable array arguments interact with argument intent attributes?
Objectives
- Understand array argument behaviour
- Make use of non-standard array bounds in a simple program
- Write a program to illustrate the interactions between
allocatableandintent(out)dummy arguments.
This section describes use of arrays as actual and dummy arguments, and some associated conditions on their use.
Functions and subroutine arguments
A number of the following features require that procedure interfaces be explicit. As we recommend procedures are always placed in modules, we will assume this is always the case unless otherwise stated.
Explicit shape
An array may be passed explicitly with information on its shape as part of the dummy argument list:
This is ok; for large rank objects this can become a little verbose. The shapes of actual and dummy arguments must agree.
Assumed shape arguments
As an array in Fortran is a self-describing object, there is the option to use assumed shape:
The size of the dummy argument can be recovered via
size() etc. Note that it is the shape that is
passed, not the bounds; this can lead to errors without some care.
Consider:
The dummy argument in this case would have a size
nmax + 1 and a default lower bound of 1. This
may not be what is expected.
Example (5 minutes)
Array arguments bounds (continued)
Bonus question: why do we need the optional argument dim
in the lbound() and ubound() invocations in
the subroutine?
The intrinsic functions lbound and ubound
by default return a rank-1 array containing the lower or upper bounds of
all dimensions. Passing the optional argument dim instead
returns the scalar bound corresponding to that dimension of the
array.
Automatic objects
A procedure may allocate space for temporary objects which come into existence when the procedure is invoked, e.g.:
FORTRAN
subroutine array_operation(a)
real, intent(in) :: a
real :: tmp(1:size(a)) ! temporary storage
Such a temporary array, for which the size may not be known at compile time, is referred to as an automatic data object and is likely to be allocated on the stack. It will have a lifetime of the execution of the procedure. Automatic data objects cannot have an initial value as part of their declaration.
However, it is generally considered poor software engineering practice to put large objects on the stack. Heap storage may be preferred.
Assumed size arrays
Older code may contain the following syntax:
The * denotes an assumed size array (distinct
from assumed shape). This is something more akin to the plain C
pass-by-reference: a pointer. However, it is potentially error-prone as
it does not provide access to shape information of the associated actual
argument.
One should prefer the explicit shape, assumed shape, or allocatable options of Modern Fortran.
Allocatable arguments
Arguments to procedures may have the allocatable
attribute.
The procedure will receive the allocation status of the object on entry. A number of conditions apply:
- The corresponding actual argument must also be allocatable.
- The rank must be specified.
- Actions changing the allocation status of the actual argument must occur via the dummy argument.
Well-written procedures may need to check the allocation status of
any allocatable arguments with allocated() before action is
taken.
Intent
The intent concerns both the allocation status of the dummy argument
as well as the data. Dummy arguments with the allocatable
attribute should follow these rules:
- An argument with
intent(in)may not be allocated or deallocated (and the values may not be altered as for a normalintent(in)argument). - An argument with
intent(out)is automatically deallocated on entry if already allocated.
The second point may cause some surprises. An intent of
inout must be used if any information from the actual
argument is to be visible in the procedure.
Array sections as arguments
We may pass an array section as an actual argument. Consider:
FORTRAN
subroutine my_array_operation(a)
real, intent(inout) :: a(:)
! ... some operation on all elements...
end subroutine my_array_operation
We may invoke this as
to operate on the odd-indexed elements. How has this worked? In
practice, the compiler has probably made a temporary copy of the section
as a contiguous array (with three elements). The copy is passed to the
subroutine, and the result copied out again. The relevant values are
then set in the original array a(1:5). The temporary array
is destroyed.
This process is usually referred to as “copy-in, copy-out”. In Fortran, the compiler is given the freedom to do this if it is deemed appropriate. So Fortran cannot be described as “call by reference” or “call by value”. The standard only says the mechanism “is usually similar to call by reference”.
Exercise (10 minutes)
Allocatable array arguments
Write a short example along the lines of example2.f90 to
check that an allocatable dummy argument with intent out is
indeed deallocated on entry to the subroutine.
Example output might look like
OUTPUT
Initial values 1.00000000 2.00000000 3.00000000 4.00000000 5.00000000
The argument b is unallocated
Final values
Allocatable array arguments (continued)
Can an array section be passed to a subroutine where the corresponding dummy argument has been declared alloctable?
No, as the actual argument and intermediate array slice’s allocation status may not be the same after the call.
Allocatable array arguments (continued)
What happens if a function with an allocatable result returns with the result in an unallocated state?
The variable assignment will be unallocated.
- Arrays passed as arguments retain their size, not their bounds
- Array arguments behave as though passed by reference, however array sections may require copy-in, copy-out