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