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

问题描述 投票:1回答:2

我听说,在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语言的标准或依赖于编译器实现。

fortran fortran90
2个回答
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以获得详细解释。)


2
投票

这样的测试无法证明什么。一些垃圾在两个函数调用之间保留在堆栈中的事实可能是纯粹的巧合。

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

© www.soinside.com 2019 - 2024. All rights reserved.