2.4. Program Execution

During program execution, constructs and statements are executed in a prescribed order. Variables become defined with values and can be redefined later in the execution sequence. Procedures are invoked, perhaps recursively. Space can be allocated and later deallocated. Pointers can change their targets.

2.4.1. Execution Sequence

Program execution begins with the first executable construct in the main program. An executable construct is an instruction to perform one or more of the computational actions that determine the behavior of the program or control the flow of the execution of the program. It can perform arithmetic, compare values, branch to another construct or statement in the program, invoke a procedure, or read from or write to a file or device. When a procedure is invoked, its execution begins with the first executable construct after the entry point in the procedure. On normal return from a procedure invocation, execution continues where it left off. The following are examples of executable statements:

     READ(5, *) Z, Y
     X = (4.0 * Z) + BASE
     IF (X > Y) GO TO 100
     CALL CALCULATE(X)
100  Y = Y + 1

Unless a branching statement or control construct is encountered, executable statements are executed in the order in which they appear in a program unit until a STOP, RETURN, or END statement is executed. Branch statements specify a change in the execution sequence and consist of the various forms of GO TO statements, a procedure reference with alternative return specifiers, and input/output (I/O) statements with branch label specifiers such as ERR=, END=, and EOR= specifiers. The control constructs (IF, CASE, and DO) can cause internal branching implicitly within the structure of the construct. Chapter 8, discusses control flow within a program in detail.

2.4.2. Definition and Undefinition

Most variables have no value when execution begins; they are considered to be undefined. Exceptions are variables that are initialized in DATA statements, type declaration statements, or variables whose type is a structure for which full default initialization is specified in the structure definition (all components must be fully initialized); these are considered to be defined. A variable can acquire a value or change its current value, typically by the execution of an assignment statement or an input statement. Thus it can assume different values at different times, and under some circumstances it can become undefined. Defined and undefined are the Fortran terms that are used to specify the definition status of a variable. The Fortran Language Reference Manual, Volume 2, describes the events that cause variables to become defined and undefined.

A variable is considered to be defined only if all parts of it are defined. For example, all elements of an array, all components of a structure, or all characters of a character string must be defined; otherwise, the array, structure, or string is undefined. Fortran permits zero-sized arrays and zero-length strings; these are always considered to be defined.

Pointers have both a definition status and an association status. When execution begins, the association status of all pointers is undefined unless one of the following conditions is present:

During execution a pointer can become nullified by the execution of a NULLIFY statement, in which case its association status becomes disassociated, or it may become associated with a target by the execution of an ALLOCATE or pointer assignment statement, in which case its association status becomes associated. Even when the association status of a pointer is defined, the pointer is not considered to be defined unless the target with which it is associated is defined. Pointer targets become defined in the same way that other variables becomes defined, typically by the execution of an assignment or input statement. When an allocatable array is allocated by the execution of an ALLOCATE statement, it is undefined until some other action occurs that causes it to become defined with values for all array elements.

2.4.3. Dynamic Behavior

Fortran supports the following types of dynamic behavior:

Many algorithms can be expressed with the use of recursion, which occurs when a subroutine or function references itself, either directly or indirectly. The keyword RECURSIVE must be present in the SUBROUTINE or FUNCTION statement if the procedure is referenced recursively. Recursive subroutines and functions are described in the Fortran Language Reference Manual, Volume 2.

No space exists for a pointer until the pointer is allocated or associated with an existing target. No space exists for an allocatable array until the array is allocated. The rank of array pointers and allocatable arrays is fixed by declaration, but the extents in each dimension (and thus the size of the arrays) is determined during execution by calculation or from input values.

The ALLOCATE and DEALLOCATE statements give Fortran programmers mechanisms to configure objects to the appropriate shape. Only pointers and allocatable arrays can be allocated. It is not possible to deallocate an object unless it was previously allocated, and it is not possible to deallocate a part of an object unless it is a pointer component of a structure. It is possible to inquire whether a pointer is currently associated and whether an allocatable array is currently allocated. Chapter 5, describes the declaration of pointers and allocatable arrays. Chapter 6, describes the ALLOCATE and DEALLOCATE statements. The Fortran Language Reference Manual, Volume 2, describes the ASSOCIATED(3i) intrinsic inquiry function for pointers and the ALLOCATED(3i) intrinsic inquiry function for allocatable arrays.

Pointers are more flexible than allocatable arrays, but they are also more complicated and less efficient. A pointer need not be an array; it can be a scalar of any type. A pointer need not be associated with allocated space; any object with the TARGET attribute can become a pointer target. A pointer assignment statement is provided to associate a pointer with a target (declared or allocated). It makes use of the symbol => rather than the single character =. In all other respects, pointer assignment statements are executed in the same way that ordinary assignment statements are executed, except that instead of assigning a value they associate a pointer with a target, as is shown in the following example:

REAL, TARGET :: VECTOR(100)
REAL, POINTER :: ODDS(:)
   . . .
ODDS => VECTOR(1:100:2)

The pointer assignment statement associates ODDS with the odd elements of VECTOR. The following assignment statement defines each odd element of VECTOR with the value 1.5:

ODDS = 1.5

Later in the execution sequence, pointer ODDS could become associated with a different target by pointer assignment or allocation, as long as the target is a one-dimensional, real array. Chapter 7, describes the pointer assignment statement.