Variable Scope

Scope is the range over which a particular variable is defined and can have a value. In Fortran, scope is defined by the program unit. A calling unit may have a variable named x, and a function may also have a variable named x, and if x is not an argument to the function then it will be distinct from the x in the calling unit.

x=20.
call sub(x)

etc.

subroutine sub(y)
real, intent(inout) :: y
real                :: x

x=10.
y=30.

end subroutine sub

An interface is also a scoping unit.

program 
   implicit none
   real   :: x
   interface
      function myfunc(x)
      real, intent(in) :: x
      end function
   end interface
end program

In the above example, the x in the interface is not connected to the x in the interface.

A variable that is only in scope in a particular unit is said to be local to that unit. Variables that are visible from more than one unit are global to those units.

BLOCK

The Fortran 2008 standard introduced the BLOCK construct. A BLOCK is a scoping unit that is finer-grained than the program-unit level. Variables may be declared within a BLOCK. Variables declared within the block are local to it. Variables declared outside the block are global to it.

IMPLICIT statements cannot appear in a block, but they do affect variables within the block.

program blocker
   implicit none
   real    ::  x,y

      x=10.5
      y=12.0

      block
         real  :: x
         x=9.1
         write(*,*) "In the block", x,y
      end block
      write(*,*) "Outside the block", x,y

      call mysub(11)
end program

subroutine mysub(n)
   implicit none
   integer :: n,ns
      if (n>0) then
         block
            integer :: ns
            ns = sqrt(real(n))
            print *, ns
         end block
         print *, ns
      endif
      if (n>0) then
         block
            integer :: ns=4
            print *,ns
         end block
      end if
end subroutine 

CONTAINS and Nested Procedures

CONTAINS is a way to nest procedures within another unit. The CONTAINS keyword extends the scope into the contained program unit. The end of the “container” must follow the end of the “containee” A contained subprogram can access all the variables in the container except those that are explicitly passed. The interface is implicit and should not be made explicit. Only one level of nesting is permitted.

Example

PROGRAM myprog
IMPLICIT NONE
   REAL  ::x,y,z

   x=5.; y=10.
   CALL mysub(z)

   CONTAINS

      SUBROUTINE mysub(w)
         REAL, INTENT(INOUT) :: w
            w=x+y
      END SUBROUTINE

END PROGRAMm

COMMON and INCLUDE

COMMON is a deprecated feature that is frequently seen in older code. It is a means of providing global variables. Global variables are variables that are in scope in at least the entire file in which they are declared; they are a frequent source of bugs since they may result in a “memory” that should not be present.

common /comname/ var1, var2, var3

The variables in the common list will be available to any program unit that includes the above line. Variables in common between two program units should not be passed as subroutine parameters. Newer code should use modules rather than COMMON.

Pitfalls with Common

The COMMON statement must be in every program unit that will share the variables, and it must be identical in each one. It is highly recommended that any code using common put each one into a separate file and use the INCLUDE statement to merge the files. INCLUDEis a standard Fortran statement, not a preprocessor statement; its syntax is

include 'file.h'

where file.h can be any name; Fortran does not have a rule about file extensions for included files.

COMMON is a frequent source of memory errors. COMMON makes interface control difficult to impossible.

The recommended first step in updating old code is to replace all COMMON with modules and then gradually to move the variables into the appropriate parameter lists.

COMMON is a vestige of the early computer era, when main memory was measuring in megabytes or even kilobytes, and every byte was precious. With COMMON the global variables would occupy a single spot in memory, would not be copied, and could be reused. In particularly old code it is not unusual for arrays in COMMON to be reshaped implicitly, since COMMON inherently represents a large linear block of memory. Sometimes the EQUIVALENCE statement is still seen, by which types could be converted implicitly as long as they occupied the same number of bytes.

Previous
Next