For example, the following defines a very simple 100 element integer stack,
MODULE stack
INTEGER, PARAMETER :: stack_size = 100
INTEGER, SAVE :: store(stack_size), pos = 0
END MODULE stack
If stack_size and pos did not have the SAVE attribute and the module was not constantly in use in at least one program unit then these objects would not be persistent. It is necessary to either USE the module in the main program or else give the global objects the SAVE attribute. The latter is the safest! The declaration of stack_size as a PARAMETER allows the stack size to be easily modified; it does not need the SAVE attribute (because its a constant).
Two (EXTERNAL) access functions can be defined to implement the stack. Both use the module containing the global data,
SUBROUTINE push(i)
USE stack
IMPLICIT NONE
INTEGER, INTENT(IN) :: i
IF (pos < stack_size) THEN
pos = pos + 1; store(pos) = i
ELSE
STOP 'Stack Full error'
END IF
END SUBROUTINE push
SUBROUTINE pop(i)
USE stack
IMPLICIT NONE
INTEGER, INTENT(OUT) :: i
IF (pos > 0) THEN
i = store(pos); pos = pos - 1
ELSE
STOP 'Stack Empty error'
END IF
END SUBROUTINE pop
A main program can now call push and pop which simulate adding to and removing from a 100 element INTEGER stack. The current state of the stack, that is, the number of elements on the sack and the values of each location, are stored `behind the scenes' in a module as global data -- this is much neater than using COMMON block. Any program that USE s stack has access to the global stack with whatever data is currently stored there.
Actually this is not the ultimate way of simulating a stack but demonstrates global data. (See later for an improvement.)
Return to corresponding overview page