SAVE attribute scope

I’d say save is the opposite of “going out of scope”. It’s telling the compiler to preserve the value “alive” between function calls. It’s essentially part of the global state, but only visible internally within the procedure. Here’s the general concept: Static variable - Wikipedia

If it helps, you can imagine save as a static variable within a function in C:

// count.c
#include <stdio.h>

void count(int *value) 
{
   static int counter_ = 0;
   counter_++;
   if (value) *value = counter_;
}

#define nil (void *) 0

int main() {

   count(nil);
   count(nil);
   count(nil);

   int value;
   count(&value);
   printf("counter = %d\n", value);
   
   return 0;
}
}
! count.f90
program main
implicit none
integer :: value

call count()
call count()
call count()

call count(value)
print *, "count = ", value

contains

   subroutine count(value)
      integer, intent(out), optional :: value
      integer, save :: counter_ = 0
      counter_ = counter_ + 1
      if (present(value)) value = counter_
   end subroutine

end program

If you don’t want save anymore, e.g. to make the library thread-safe, or other reasons, the right approach would be to encapsulate the save’d variables into a derived type/struct, which is passed between calls.

      type :: dgetv0_state
         logical :: first, inits, orth
         integer :: idist, iseed(4), iter, msglvl, jj
         double precision :: rnorm0
      end type

      subroutine dgetv0
     &   ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm,
     &     ipntr, workd, ierr, state )
C                              ^-- extra dummy argument
C ...
      type(dgetv0_state), intent(inout) :: state

The caller would be expected to keep the values in state intact without modification.

1 Like