Common blocks |
Fortran 77 has no global
variables, i.e. variables that are shared among several program units
(subroutines).
A D V E R T I S E M E N T
The only way to pass information between subroutines we have seen
so far, is to use the subroutine parameter list. Sometimes this is inconvenient,
e.g. when many subroutines share a large set of parameters. In such cases one
can use a common block. This is a way to specify that certain variables
should be shared among certain subroutines. But in general, the use of common
blocks should be minimized.
Example
Suppose you have two parameters
alpha and beta that many of your subroutines need. The following example shows
how it can be done using common blocks.
program main
some declarations
real alpha, beta
common /coeff/ alpha, beta
statements
stop
end
subroutine sub1 (some arguments)
declarations of arguments
real alpha, beta
common /coeff/ alpha, beta
statements
return
end
subroutine sub2 (some arguments)
declarations of arguments
real alpha, beta
common /coeff/ alpha, beta
x statements
return
end
|
Here we define a common block
with the name coeff.
The content of the common block is the two variables
alpha and
beta. A common block can contain as many variables
as you like. They do not need to all have the same type. Every subroutine that
wants to use any of the variables in the common block has to declare the whole
block.
Note that in this example we
could easily have avoided common blocks by passing alpha and beta as parameters
(arguments). A good rule is to try to avoid common blocks if possible. However,
there are a few rare cases where there is no other solution.
Syntax
common / name / list-of-variables
You should know that
The
common statement
should appear together with the variable declarations, before the executable
statements.
Different
common blocks must have different names (just like variables). A variable can
belong to more than one common block.
The variables
in a common block do not need to have the same names each place they occur
(although it is a good idea to do so), but they must be listed in the same order
and have the same type.
To illustrate this, look at the following continuation of
our example:
subroutine sub3 (some arguments)
declarations of arguments
real a, b
common /coeff/ a, b
statements
return
end
This declaration is equivalent
to the previous version that used
alpha and
beta. It is
recommended that you always use the same variable names for the same common
block to avoid confusion. Here is a dreadful example:
subroutine sub4 (some arguments)
declarations of arguments
real alpha, beta
common /coeff/ beta, alpha
statements
return
end
Now alpha is the beta from the main program and vice versa.
If you see something like this, it is probably a mistake. Such bugs are very
hard to find.
Arrays in common blocks
Common blocks can include
arrays, too. But again, this is not recommended. The major reason is
flexibility. An example shows why this is such a bad idea. Suppose we have the
following declarations in the main program:
program main
integer nmax
parameter (nmax=20)
integer n
real A(nmax, nmax)
common /matrix/ A, n,
nmax
This common block contains first
all the elements of A, then the integers n and nmax. Now assume
you want to use the matrix A in some subroutines. Then you have to include the
same declarations in all these subroutines, e.g.
subroutine sub1 (...)
integer nmax
parameter (nmax=20)
integer n
real A(nmax, nmax)
common /matrix/ A, n,
nmax
Arrays with variable dimensions
cannot appear in common blocks, thus the value of nmax has to be exactly
the same as in the main program. Recall that the size of a matrix has to be
known at compile time, hence nmax has to be defined in a parameter statement. It
would be tempting to delete the parameter statement in the subroutine since nmax
belongs to the common block, but this would be illegal.
This example shows there is
usually nothing to gain by putting arrays in common blocks. Hence the preferred
method in Fortran 77 is to pass arrays as arguments to subroutines (along with
the leading dimensions).