Fortran中的变量和静态数组的生存期

时间:2019-04-12 20:20:05

标签: fortran fortran90

我听说在Fortran77中,函数中的所有局部变量都是在主程序执行开始时创建的,并且在整个运行时都存在,而不是在函数进入时创建并在退出时销毁。我不知道在更新的Fortran中是否仍然如此。有什么办法可以验证这一点吗? 一种可能有用的测试是检查变量在两次调用之间是否保留其值。这是一个简单的测试:

  program main
  call p()
  call p()
  call p()
 end program main

 subroutine p()
  real :: a(3)
  a=a+1
  write(*,*) a(1), a(2), a(3)
 end subroutine p

我使用gfortran进行的测试表明,数组a在调用之间保留其值,其行为与所使用的save属性相同。 我想知道这是Fortran语言的标准还是取决于编译器的实现。

2 个答案:

答案 0 :(得分:2)

这样的测试无法证明任何事情。在两次函数调用之间的堆栈中仍残留一些垃圾的事实可能纯粹是巧合。

局部函数变量仅在定义其值的函数调用期间有效。在Fortran 77中也是如此。如果应保留该值,则必须将变量声明为SAVE

答案 1 :(得分:2)

只是为了好玩,我们可以尝试一个程序,其中可以在foo()的连续调用之间调用其他例程(例如p()):

program main
    call p()
    !  call foo()  ! (*)
    call p()
    !  call foo()  ! (*)
    call p()
end

subroutine p()
    real :: a(3)
    a = a + 1
    write(*,*) "a = ", a
end

subroutine foo()
    real :: b(3)
    b = b * 10
    write(*,*) "b = ", b
end

用(*)行注释,我们得到

 ! gfortran-8.2
 a =    1.00000000       4.74066630E+21   1.00000000    
 a =    2.00000000       4.74066630E+21   2.00000000    
 a =    3.00000000       4.74066630E+21   3.00000000

 ! PGI18.10
 a =     1.000000        1.000000        1.000000    
 a =     2.000000        2.000000        2.000000    
 a =     3.000000        3.000000        3.000000    

在未注释行(*)的情况下,我们得到

 ! gfortran-8.2
 a =    1.00000000       4.74066630E+21   1.00000000    
 b =    10.0000000       4.74066641E+22   10.0000000    
 a =    11.0000000       4.74066641E+22   11.0000000    
 b =    110.000000       4.74066623E+23   110.000000    
 a =    111.000000       4.74066623E+23   111.000000

 ! PGI18.10
 a =     1.000000        1.000000        1.000000    
 b =     0.000000        0.000000        0.000000    
 a =     2.000000        2.000000        2.000000    
 b =     0.000000        0.000000        0.000000    
 a =     3.000000        3.000000        3.000000  

(这只是对局部变量的行为进行的实验/说明(即不一定会“ SAVE-ed”,因为在较简单的情况下可能会出现),请参见the other answer and comments以获取详细说明。)< / p>