Arrays
Last updated on 2026-07-21 | Edit this page
Estimated time: 20 minutes
Overview
Questions
- How are arrays declared?
- How can array sizes be determined at runtime?
Objectives
- Understand how to define static and dynamic arrays
- Diagnose and debug array definitions in simple programs
Declarations
We may declare arrays of intrinsic type with a fairly elastic syntax, e.g.:
Note that the declaration e(10, 3) will override the
dimension(10, 2) statement, however this mix and match
approach is generally discouraged.
One may also omit the dimension attribute:
The two declarations of b(10,2) above are equivalent. If
one restricts oneself to one variable declaration per line, then the
second form is more concise, and will be preferred in the rest of this
course.
Arrays have a rank, a size (the number of elements). The sequence of
extents in each dimension is the shape. The array in Fortran is a
self-describing object and its properties may be interrogated via
intrinsic functions: size(), shape(),
lbound(), and ubound().
There is an array element order which has the left-most index counting fastest; we expect this to correspond to contiguous locations in memory.
There are a number of ways one may obtain array sections or array-valued objects which may not be contiguous:
Array constructors
There are a number of ways to provide initial values for array elements:
FORTRAN
integer, parameter :: j(3) = (/ -1, 0, +1 /) ! F2003
integer, parameter :: k(3) = [ -1, 0, +1 ] ! F2008
One may also use an implied do construction:
FORTRAN
integer :: i
real, parameter :: s(300) = [ (i, i = 1,300) ]
real :: t(3) = [ (2.0*(i*i + 1), i = 1,3) ]
Older code may also see use of the data statement to
initialise tables of values. This has the form:
where the data-statement-set consists of pairs of
That is, one associates a list of values with a list of variables, e.g.:
The data statement is quite flexible in syntax, but
generally can be omitted in favour of array constructors or other “more
modern” facilities. The data statement cannot be used to
initialise allocatable or pointer variables.
Heap storage
Storage for arrays may be established at run time via the
allocatable attribute, e.g.:
The allocation status of the array may be interrogated via
the intrinsic function allocated().
Assignment as allocation
One may combine allocation with initialisation in a number of ways including:
FORTRAN
real, allocatable :: a(:)
real, allocatable :: b(:)
real, allocatable :: c(:)
a = [ 1.0, 2.0, 3.0 ] ! status now allocated
allocate(b, source = a) ! "sourced allocation"
c = b(:)
Automatic reallocation is also possible for intrinsic assignments, e.g., following on from the above:
Allocatable scalars are allowed and may be useful in some circumstances.
Zero-sized arrays
Formally, a zero-sized allocation is not well defined by
malloc() in C. However, as Fortran arrays are objects,
zero-sized arrays are possible:
This can make it easier to write generic code which does not have to include conditionals to handle edge-cases where the array size might go to zero.
Two zero-sized arrays of the same rank may have different shapes, and so do not necessarilty conform (although a zero-sized array always conforms with a scalar, as usual). As a zero-sized array has no elements, it is always considered to be defined.
Exercise (5 minutes)
Correcting array programs
Look at the accompanying programs to be found in the directory
episodes/files/exercises/01-arrays within this
repository:
problem1.f90 ! needs completing
problem2.f90 ! will fail to compile; correct the code
problem3.f90 ! will fail at run time; what is the problem?
These may be compiled with, e.g.,
The compiler should highlight the source of the issue: i
is undefined. The values in the array will still not be as requested.
After fixing you should obtain the expected output
OUTPUT
Initial values 10.0000000 20.0000000 40.0000000
using the array constructor
real :: t(3) = [ (10.0*(2**(i-1)), i = 1, 3) ]
The program will SEGFAULT at runtime as a
has not been allocated. Confirm this by copying the line to print
Status to the point just before the array accesses are
performed:
OUTPUT
Status F
Allocating the array before accessing will allow the program to run correctly
OUTPUT
Status F # Before allocation
Status T # After allocation
Values 1.00000000 2.00000000 3.00000000
Alternatively, to perform assignment and allocation simultaneously,
as described above, turn a(:) = ... into
a = ....
Exercise (5 minutes)
Array safety
As arrays are self-describing in Fortran, it is relatively easy for
the compiler to analyse whether array accesses are valid, or within
bounds. This can help debugging. Most compilers will have an option that
instructs the compiler to inject additional code which checks bounds at
run time. For the Cray Fortran compiler, this is -hbounds;
for the GNU gfortran compiler, this is
-fbounds-check.
The first example contains a fixed array element reference which is incorrect. This should be visible to the compiler at compile time:
The second example prompts for an array index at run time. This may
or may not be out of bounds. Check what happens at run time if the value
of 4 is entered.
Check what happens if the tests are repeated using programs compiled without bounds checking. What are the possible dangers?
- Fortran supports both static- and dynamic-sized arrays
- Fortran arrays are objects, allowing out of bounds accesses to be checked
- The bounds of an array can be set by the programmer