3.1 Atributo SAVE

Fortran

Quando as variáveis não são inicializadas explicitamente, não se deve esperar que estejam inicializadas antes de serem usadas. Alguns compiladores, em algumas situações, podem inicializar algumas variáveis por padrão, mas isso não é algo com que se deva contar.

No Fortran 77 a declaração não executável SAVE faz com que os valores das variáveis de um procedimento sejam preservados após terminar a sua execução, impedindo que estas variáveis se tornem indefinidas. Uma declaração SAVE sem uma lista de variáveis preserva todas as variáveis locais presentes no procedimento, enquanto que com uma lista de variáveis preserva apenas as variáveis especificadas na lista.

A partir do Fortran 90 as variáveis declaradas com o atributo SAVE preservam seu valor e sua definição, associação e status de alocação após o procedimento onde foram declaradas terminar a sua execução. Não é possível presumir que variáveis declaradas sem o atributo SAVE irão preservar seu valor e status entre chamadas do procedimento, embora em algumas implementações do Fortran todas as variáveis locais e blocos comuns sejam tratados como se tivessem o atributo SAVE definido. As variáveis declaradas com valor inicial atribuído também podem ter o atributo SAVE definido implicitamente, mas é outra coisa com que não se deve contar. Não faz sentido declarar o atributo SAVE nas variáveis do programa principal, uma vez que sua finalidade é apenas preservar o valor das variáveis entre chamadas de procedimento.

Abaixo estão mostrados dois programas semelhantes, onde as variáveis locais da função e da sub-rotina estão declaradas sem o atributo SAVE, no primeiro programa, e com o atributo SAVE, no segundo programa. Os valores das variáveis são exibidos antes e depois de ter sido atribuído valor as mesmas.

Primeiro programa, variáveis declaradas sem o atributo SAVE:

FUNCTION funcao(argumento) RESULT(resultado)
    ! Função para imprimir variáveis declaradas sem o atributo SAVE
    ! presente, antes e depois de receberem um valor atribuído.
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: argumento
    INTEGER :: resultado
    INTEGER, PARAMETER :: constante_funcao = 80
    INTEGER :: variavel_local_funcao_1, variavel_local_funcao_2
    PRINT '(A14,4I12)', 'Function ->', argumento, constante_funcao, &
          variavel_local_funcao_1, variavel_local_funcao_2
    variavel_local_funcao_1 = argumento + 1
    variavel_local_funcao_2 = argumento + 2
    PRINT '(A14,4I12)', 'Function <-', argumento, constante_funcao, &
          variavel_local_funcao_1, variavel_local_funcao_2
    resultado = argumento + 60
    RETURN
END FUNCTION funcao
SUBROUTINE subrotina(argumento)
    ! Sub-rotina para imprimir variáveis declaradas sem o atributo SAVE
    ! presente, antes e depois de receberem um valor atribuído.
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: argumento
    INTEGER, PARAMETER :: constante_subrotina = 90
    INTEGER :: variavel_local_subrotina_1, variavel_local_subrotina_2
    PRINT '(A14,4I12)', 'Subroutine ->', argumento, constante_subrotina, &
          variavel_local_subrotina_1, variavel_local_subrotina_2
    variavel_local_subrotina_1 = argumento + 5
    variavel_local_subrotina_2 = argumento + 7
    PRINT '(A14,4I12)', 'Subroutine <-', argumento, constante_subrotina, &
          variavel_local_subrotina_1, variavel_local_subrotina_2
    RETURN
END SUBROUTINE subrotina
PROGRAM procedimentos
    ! Programa para chamar procedimentos que mostram
    ! os valores de variáveis não inicializadas.
    INTEGER funcao
    INTEGER valor_retornado
    INTEGER variavel_local_programa
    PRINT '(A14,I12)', 'Program:', variavel_local_programa
    PRINT '(A14,4A12)', 'Procedimento', 'Argumento', 'Constante', &
                        'Variavel 1', 'Variavel 2'
    CALL subrotina(5)
    valor_retornado = funcao(35)
    CALL subrotina(10)
    valor_retornado = funcao(40)
    CALL subrotina(15)
    CALL subrotina(20)
    valor_retornado = funcao(45)
    valor_retornado = funcao(50)
    STOP
END PROGRAM procedimentos
      Program:           0
  Procedimento   Argumento   Constante  Variavel 1  Variavel 2
 Subroutine ->           5          90           0          10
 Subroutine <-           5          90          10          12
   Function ->          35          80          12 -1226367116
   Function <-          35          80          36          37
 Subroutine ->          10          90          95          36
 Subroutine <-          10          90          15          17
   Function ->          40          80          17          37
   Function <-          40          80          41          42
 Subroutine ->          15          90         100          41
 Subroutine <-          15          90          20          22
 Subroutine ->          20          90          20          22
 Subroutine <-          20          90          25          27
   Function ->          45          80          27          42
   Function <-          45          80          46          47
   Function ->          50          80          46          47
   Function <-          50          80          51          52

Segundo programa, variáveis declaradas com o atributo SAVE (diferenças):

FUNCTION funcao(argumento) RESULT(resultado)
    ! Função para imprimir variáveis declaradas com o atributo SAVE
    ! presente, antes e depois de receberem um valor atribuído.
...
    INTEGER, SAVE :: variavel_local_funcao_1, variavel_local_funcao_2
...
END FUNCTION funcao
    ! Sub-rotina para imprimir variáveis declaradas com o atributo SAVE
    ! presente, antes e depois de receberem um valor atribuído.
...
    INTEGER, SAVE:: variavel_local_subrotina_1, variavel_local_subrotina_2
...
END SUBROUTINE subrotina
PROGRAM procedimentos
...
END PROGRAM procedimentos
      Program:           0
  Procedimento   Argumento   Constante  Variavel 1  Variavel 2
 Subroutine ->           5          90           0           0
 Subroutine <-           5          90          10          12
   Function ->          35          80           0           0
   Function <-          35          80          36          37
 Subroutine ->          10          90          10          12
 Subroutine <-          10          90          15          17
   Function ->          40          80          36          37
   Function <-          40          80          41          42
 Subroutine ->          15          90          15          17
 Subroutine <-          15          90          20          22
 Subroutine ->          20          90          20          22
 Subroutine <-          20          90          25          27
   Function ->          45          80          41          42
   Function <-          45          80          46          47
   Function ->          50          80          46          47
   Function <-          50          80          51          52

Como pode ser visto pelos resultados das execuções dos programas, quando foi utilizado o atributo SAVE as variáveis foram inicializadas com o valor zero, como no programa principal, enquanto que quando não foi utilizado o atributo SAVE as variáveis não foram inicializadas e depois ficaram com valores que parecem oriundos da última execução da mesma ou de alguma outra função ou sub-rotina, ou seja, lixo. Mesmo assim, não se deve esperar que sejam inicializadas com o valor zero quando o atributo SAVE está presente na declaração da variável.

Referências