Fortran中变量和静态数组的生存期
我听说,在Fortran77中,函数中的所有局部变量都是在主程序执行开始时创建的,并且在整个运行时都存在,而不是在函数进入时创建,在退出时销毁。我不知道这在较新的Fortran中是否仍然正确。有没有什么办法可以检验一下? meight帮助的一个测试是检查变量在调用之间是否保留其值。下面是一个简单的测试:Fortran中变量和静态数组的生存期,fortran,fortran90,Fortran,Fortran90,我听说,在Fortran77中,函数中的所有局部变量都是在主程序执行开始时创建的,并且在整个运行时都存在,而不是在函数进入时创建,在退出时销毁。我不知道这在较新的Fortran中是否仍然正确。有没有什么办法可以检验一下? meight帮助的一个测试是检查变量在调用之间是否保留其值。下面是一个简单的测试: program main call p() call p() call p() end program main subroutine p() real :: a(3)
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 77中也是如此。如果应该保留该值,则必须声明变量h已保存。这样的测试无法证明任何事情。在两次函数调用之间,堆栈中仍然存在一些垃圾,这完全是巧合
局部函数变量仅在定义其值的函数调用期间有效。在Fortran 77中也是如此。如果该值应该保留,变量hh必须声明为SAVE。只是为了好玩,我们可以尝试一个程序,在连续调用p之间可以调用一些其他例程,例如foo: 有了这些行*注释,我们得到了
! 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
当行*未注释时,我们得到
! 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
这只是局部变量行为的一个实验/说明,即不必像在更简单的情况下出现的那样保存,请参阅以获取详细解释。为了好玩,我们可以尝试一个程序,在连续调用p之间可以调用一些其他例程,例如foo: 有了这些行*注释,我们得到了
! 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
当行*未注释时,我们得到
! 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
这只是局部变量行为的一个实验/说明,即不必像在更简单的情况下出现的那样保存,详细解释请参见。如果测试表明一个非常大的数组中的每个元素在两次函数调用之间都保留其值,那么该测试将证明是正确的,即。,本地数组的生存期是整个执行过程,而不局限于函数调用。我说的是生存期,但你回答的第二句话谈到了范围。@YoujunHu你完全错了,如果测试表明元素保留了它们的值,那证明什么都没有。也就是说,数据只是作为无效垃圾保留在那里,即使它留在内存中,也不允许您读取它。幸运的是,数组碰巧是静态的,或者堆栈在每次调用时的布局都是相同的。@YoujunHu您的另一条评论也是错误的。关于SAVE的评论是关于生存期的,而不是关于范围的。只有使用“保存”时,即使数组超出范围,它仍然有效。如果不保存,则一旦过程返回,该值将被取消定义。Fortran 77不需要对递归的支持,隐式保存相当常见。如果要确定在ou超出作用域时数据是否被覆盖,至少必须调用另一个过程,该过程可能会将数据存储在同一地址空间中,然后才能查看数据是否被保留。如果测试表明超大数组的每个元素在两次函数调用之间都保留其值,该测试将证明某些事情,即本地数组的生存期是整个执行过程,而不限于函数调用。我说的是生存期,但你回答的第二句话谈到了范围。@YoujunHu如果测试表明元素保留其值,你完全错了,这完全证明不了什么。也就是说,数据只是作为无效垃圾保留在那里,即使它留在内存中,也不允许您读取它。幸运的是,数组碰巧是静态的,或者堆栈在每次调用时的布局都是相同的。@YoujunHu您的另一条评论也是错误的。关于SAVE的评论是关于生存期的,而不是关于范围的。只有使用“保存”时,即使数组超出范围,它仍然有效。如果不保存,则一旦过程返回,该值将被取消定义。Fortran 77不需要对递归的支持,隐式保存相当常见。如果你想知道当你离开作用域时数据是否被覆盖,至少你必须调用另一个过程,该过程可能会将数据存储在同一个地址空间中,然后再查看数据是否被保留。当这是公认的答案时,你能至少添加问题的实际答案吗,为了未来游客的利益?只是
对这些值进行更改的注释是可以的。@VladimirF Hi,我已经添加了一个指向您答案的指针,我认为这也应该被接受。事实上,我的只是为了好玩尝试其他编译器可能也很有趣,但不幸的是,我没有访问atm的权限。当这是公认的答案时,为了将来的访问者的利益,您能否至少添加问题的实际答案?只需一句评论,说明这些值已更改就可以了。@VladimirF Hi,我已经添加了一个指向您答案的指针,我也认为应该接受。事实上,我的只是为了好玩尝试其他编译器可能也很有趣,但不幸的是我没有访问atm的权限。