16. Common blocks

Fortran 77 has no global variables, i.e. variables that are shared among several program units (subroutines). 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

      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 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).


Exercises

Exercise A
Rewrite this program and subprogram such that they do not use common blocks. Keep the overall structure.
      program main
      real origo(3), x(3)
      real d, dist
      common /silly/ origo
      
      read(*,*) origo(1), origo(2), origo(3)
  10  continue
         read(*,*) x(1), x(2), x(3)
         d = dist(x)
         write(*,*) 'The distance is ', d
      if (x(1).ge.0.) goto 10

      stop
      end
      
      real function dist (x)
      real x(3)
      real x0, y0, z0
      common /silly/ x0, y0, z0

      dist = sqrt((x(1)-x0)**2 + (x(2)-y0)**2 + (x(3)-z0)**2)

      return
      end


[Fortran Tutorial Home]
boman@sccm.stanford.edu