Fortran 中变量和静态数组的生命周期
lifetime of variables and static arrays in Fortran
听说,在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 77 中也是如此。如果要保留该值,则必须声明变量 hhave SAVE
.
只是为了好玩,我们可以尝试一个程序,其中可以在连续调用 p()
之间调用其他一些例程(例如 foo()
):
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
(这只是局部变量行为的 experiment/illustration(即不一定 "SAVE-ed",因为它可能出现在更简单的情况下),请参阅 了解详细信息解释。)
听说,在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 77 中也是如此。如果要保留该值,则必须声明变量 hhave SAVE
.
只是为了好玩,我们可以尝试一个程序,其中可以在连续调用 p()
之间调用其他一些例程(例如 foo()
):
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
(这只是局部变量行为的 experiment/illustration(即不一定 "SAVE-ed",因为它可能出现在更简单的情况下),请参阅