Lengthy argument lists in subroutines and user-defined functions can occur
as modularised programs grow ever larger, requiring more and more information
to be passed between program units. The
COMMON block, a piece
of shared memory in the computer, is another method for passing information
between program units. Data stored in a
COMMON block is not
passed between program units via argument lists, but through the
COMMON statement near the beginning of each program unit.
There are two types of
COMMON blocks: blank and
named. A program may contain only one blank
COMMON block but any number of named
COMMON block must be declared in every program unit in which
the information stored therein is needed. In addition, the unique
COMMON block must be declared in the main program.
COMMON block is set up with the statement
and the named
COMMON block is declared by
COMMON /name/ variable-list
where the name between the forward slashes is the name of the
Every subroutine or user-defined function that uses data stored in the
COMMON block, blank or named, must have a similar statement
to those above. The variable names do not need to match between program
units but it is vital that their types and the order in which they appear
in the list are identical.
Consider the following program fragment:
PROGRAM MAIN INTEGER A REAL F,R,X,Y COMMON R,A,F A = -14 R = 99.9 F = 0.2 CALL SUB(X,Y) … END SUBROUTINE SUB(P,Q) INTEGER I REAL A,B,P,Q COMMON A,I,B … END
In this example, a blank
COMMON block holds three values: a
REAL number, an
INTEGER number, and another
REAL number. Memory is shared in the
block in the following way:
|Main Program||Common Memory Storage||Subroutine|
Note that the variable names for each memory area differ between the main program and the subroutine, but that the number and type of variables are the same as is the order in which they are listed.
COMMON blocks are used in much the same manner. Note
that a variable cannot appear in more than one named
block in a program unit.
COMMON blocks must be declared in the main program.
It is not necessary to declare named
COMMON blocks in the
main program unless they are used there.
COMMON blocks need not be the same length in
different program units. However, a named
COMMON block must
be exactly the same length wherever it appears. This means that
some knowledge about how the computer stores information is necessary.
That is, the programmer must know how much storage each variable or
array takes in order to ensure that the named
are the same length.
Variables in blank
COMMON blocks may be initialised with
READ or assignment statements but not with a
DATA statement. The same restrictions apply to named
COMMON blocks with one important difference: named
COMMON blocks may be initialised in a special nonexecutable
subroutine called a
BLOCK DATA subprogram.
When a subroutine or function is exited, local variables become
undefined. The same thing may happen with the variables stored in
COMMON blocks. Therefore, it is possible to
SAVE an entire named
COMMON block (but not
individual variables in the block) in a procedure with the command
SAVE /named common block1/, /named common block2/, …, /named common blockn/
Variables in a blank
COMMON block never become undefined since
the it is declared in the main program. Similarly, if a named
COMMON block is declared in the main program, then it is
unecessary to use the
SAVE command in other program units.
Note that you cannot use the
SAVE command on a blank
BLOCK DATA subprogram consists of the
BLOCK DATA statement, any necessary type declarations, a
list of the named
COMMON blocks and their variables, and one or
DATA statements initialising one or more of the variables
appearing in the
COMMON blocks. Its sole purpose is to
initialise the values in named
BLOCK DATA SETUP INTEGER A,B,C REAL I,J,K,L COMMON /AREA1/ A,B,C COMMON /AREA2/ I,J,K,L DATA A,B,C,I,J,K,L/0,1,2,10.0,-20.0,30.0,-40.0/ END
During compilation and linking, if one of the modules containing a procedure
is omitted, the linker will almost certainly return an error but this will
not happen if it's the
BLOCK DATA subprogram that's missing.
To avoid this possibility, the name of the
subprogram unit should be included in an
EXTERNAL statement in
some or all of the procedures which contain the named
blocks initialised by the
BLOCK DATA subprogram.
The general form of the statement is
EXTERNAL ename1, ename2, …, enamen
where ename is the name of an external function, subroutine,
BLOCK DATA subprogram or dummy procedure in an argument list.
The use of
COMMON blocks is discouraged unless there are
extremely large amounts of data to be passed between program units. The
reason for this is simple: it weakens modularity. Variables in
COMMON blocks are global in nature and when one
program unit alters a variable in this shared memory area, then it affects
all of the other program units which also use this shared area, often with
unexpected results. The debugging process becomes that much harder.
EQUIVALENCE statement causes two or more items (arrays or
variables) to occupy the same memory space. In the early days of
FORTRAN, when computer memory was measured in kilobytes, this was a valuable
technique to make the most efficient use of very limited memory. Today,
computers routinely have gigabytes of memory, but
still has a use, as the case study below demonstrates.
The general form of the statement is
EQUIVALENCE (variable-list1), (variable-list2), …, (variable-listn)
where there are one or more variable-lists. The
variable-list contains two or more variables or arrays or mixture
of the two. The
EQUIVALENCE statement occurs near the
beginning of a program unit, along with type declarations and other
Some years ago, one of the authors wrote a FORTRAN 77 program to model the dynamics of planetary satellites by numerical integration of the equations of motion. The orbits were to be fitted to observational data, so it was necessary to integrate not only the coordinates of the satellites, but also the partial derivatives of the coordinates with respect to the initial position and velocity of each satellite, in order to calculate the variational equations.
Thus the (one-dimensional) array of quantities being integrated in the case of N satellites were:
x1, y1, z1, x2, y2, z2, …, xN, yN, zN, ∂x1/∂ξ1, ∂y1/∂ξ1, ∂z1/∂ξ1, …, ∂x1/∂η1, ∂y1/∂η1, ∂z1/∂η1, …, ∂zN/∂ζ'N
where ξ1 denotes the initial value of x1, and so forth.
In the main program, the number of coordinates and free parameters were defined
PARAMETER statement as
NPARAM respectively. For a two-satellite system, there are 6
coordinates and 12 components of the initial position and velocity vectors,
Then the number of partial derivatives was defined as the product of those two quantities,
and the total number of equations to be integrated was the number of coordinates plus the number of partial derivatives,
The one-dimensional array of quantities being integrated was declared as
DOUBLE PRECISION P(NEQNS)
and the two-dimensional array of partial derivatives was declared as
DOUBLE PRECISION PTLS(NCOORD,NPARAM)
EQUIVALENCE was used to make these two array share
the same memory:
In the case of two satellites, this results in the following memory layout:
Why do this? The integration routine required a one-dimensional array of equations, but in the rest of the program, it was preferable to represent the partial derivatives as a two-dimensional array. There were three options:
P. This would greatly complicate the program, as well as increasing the likelihood of bugs due to miscalculation of the correct offset.
Pinto the array
PTLSafter every integration step. This would be slow and wasteful, because the program performs many thousands of integration steps, and the number of partial derivatives grows quadratically with the number of satellites.
EQUIVALENCEto map the two-dimensional array of partial derivatives directly onto the one-dimensional array of integrated quantities.
The third option was the most elegant and the most efficient. It demonstrates
EQUIVALENCE still has a place in modern FORTRAN 77
There are a few restrictions on the use of the
statement. Dummy arguments in external functions and subroutines cannot
appear in the variable-list nor can variables which are external
function names. It is also illegal to equivalence two or more elements of
the same array or do anything else which violates storage sequence rules.
It is possible to equivalence different numerical data types but you must
know exactly how these values are stored internally in order to do it
correctly and sensibly. The resulting code may not be portable to other
machines. Use with caution.