Fortran Modern alternatives to historical features Common Blocks


Example

In the early forms of Fortran the only mechanism for creating global variable store visible from subroutines and functions is to use the COMMON block mechanism. This permitted sequences of variables to be names and shared in common.

In addition to named common blocks there may also be a blank (unnamed) common block.

A blank common block could be declared like

common i, j

whereas the named block variables could be declared like

common /variables/ i, j

As a complete example, we could imagine a heap store that is used by routines that can add and remove values:

       PROGRAM STACKING
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       ICOUNT = 0
       READ *, IVAL
       CALL PUSH(IVAL)
       CALL POP(IVAL)
       END

       SUBROUTINE PUSH(IVAL)
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       ICOUNT = ICOUNT + 1
       ISTACK(ICOUNT) = IVAL
       RETURN
       END

       SUBROUTINE POP(IVAL)
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       IVAL = ISTACK(ICOUNT)
       ICOUNT = ICOUNT - 1
       RETURN
       END

Common statements may be used to implicitly declare the type of a variable and to specify the dimension attribute. This behaviour alone is often a sufficient source of confusion. Further, the implied storage association and requirements for repeated definitions across program units makes the use of common blocks prone to error.

Finally, common blocks are very restricted in the objects they contain. For example, an array in a common block must be of explicit size; allocatable objects may not occur; derived types must not have default initialization.

In modern Fortran this sharing of variables can be handled by the use of modules. The above example can be written as:

module heap
  implicit none
  ! In Fortran 2008 all module variables are implicitly saved
  integer, save :: count = 0
  integer, save :: stack(1023)
end module heap

program stacking
  implicit none
  integer val
  read *, val
  call push(val)
  call pop(val)

contains
  subroutine push(val)
    use heap, only : count, stack
    integer val
    count = count + 1
    stack(count) = val
  end subroutine push

  subroutine pop(val)
    use heap, only : count, stack
    integer val
    val = stack(count)
    count = count - 1
  end subroutine pop
end program stacking

Named and blank common blocks have slightly different behaviours. Of note:

  • objects in named common blocks may be defined initially; objects in blank common shall not be
  • objects in blank common blocks behave as though the common block has the save attribute; objects in named common blocks without the save attribute may become undefined when the block is not in the scope of an active program unit

This latter point can be contrasted with the behaviour of module variables in modern code. All module variables in Fortran 2008 are implicitly saved and do not become undefined when the module goes out of scope. Before Fortran 2008 module variables, like variables in named common blocks, would also become undefined when the module went out of scope.