Fortran 当传递函数名作为参数时,函数不接受数组作为输入
我正在写一个子程序,它可以将函数名作为参数。 在我的示例中,它是Fortran 当传递函数名作为参数时,函数不接受数组作为输入,fortran,Fortran,我正在写一个子程序,它可以将函数名作为参数。 在我的示例中,它是call-call\u-test(ga),其中ga是一个函数ga(x) 如果x是一个标量,我以前的做法就可以了。 问题是,如果x是数组,则程序失败 可以重现问题的最小示例是以下代码: module fun implicit none private public :: ga, call_test contains subroutine call_test(fn)
call-call\u-test(ga)
,其中ga
是一个函数ga(x)
如果x
是一个标量,我以前的做法就可以了。
问题是,如果x
是数组,则程序失败
可以重现问题的最小示例是以下代码:
module fun
implicit none
private
public :: ga, call_test
contains
subroutine call_test(fn)
double precision,external::fn
double precision::f
double precision,dimension(0:2)::x0
x0 = 0.111d0
print*,'Input x0=',x0
print*,'sze x0:',size(x0)
f = fn(x0)
print*,'fn(x0)=',f
end subroutine call_test
function ga(x) result(f)
double precision,dimension(0:) :: x
double precision::f
print*,'size x inside ga:',size(x)
print*,'x in ga is:=',x
f = sum(x)
end function ga
end module
program main
use fun
call call_test(ga)
end program main
使用最新的ifort
,我的执行结果是:
Input x0= 0.111000000000000 0.111000000000000 0.111000000000000
sze x0: 3
size x inside ga: 140732712329264
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image PC Routine Line Source
a.out 000000010C6EC584 Unknown Unknown Unknown
libsystem_platfor 00007FFF20610D7D Unknown Unknown Unknown
a.out 000000010C6C62B2 _MAIN__ 32 main.f90
a.out 000000010C6C5FEE Unknown Unknown Unknown
使用gfortran
结果是
Input x0= 0.11100000000000000 0.11100000000000000 0.11100000000000000
sze x0: 3
size x inside ga: 0
x in ga is:=
fn(x0)= 0.0000000000000000
我的问题是为什么会这样,以及如何让它起作用。基于我的代码的功能代码解决方案非常受欢迎。@IanBush的评论是正确的。您需要一个显式接口,因为函数参数采用假定的形状伪参数。由于您的代码中还有其他一些不推荐使用的功能,这里是它的现代重新实现,希望改进Fortran社区编码实践
module fun
use iso_fortran_env, only: RK => real64
implicit none
private
public :: ga, call_test
abstract interface
function fn_proc(x) result(f)
import RK
real(RK), intent(in) :: x(0:)
real(RK) :: f
end function fn_proc
end interface
contains
subroutine call_test(fn)
implicit none
procedure(fn_proc) :: fn
real(RK) :: f
real(RK) :: x0(0:2)
x0 = 0.111_RK
write(*,"(*(g0,:,' '))") 'Input x0 =',x0
write(*,"(*(g0,:,' '))") 'sze x0:',size(x0)
f = fn(x0)
write(*,"(*(g0,:,' '))") 'fn(x0) =', f
end subroutine call_test
function ga(x) result(f)
real(RK), intent(in) :: x(0:)
real(RK) :: f
write(*,"(*(g0,:,' '))") 'size x inside ga:',size(x)
write(*,"(*(g0,:,' '))") 'x in ga is:',x
f = sum(x)
end function ga
end module
program main
use fun
call call_test(ga)
end program main
注意抽象界面的使用
。import
语句仅导入符号RK以便在摘要中使用。没有它,您将不得不使用iso_fortran_env
将RK
声明为real64
。不要使用双精度,它已被弃用,不一定意味着64位实数。另外,请注意0.111d0
到0.111_-RK
的转换。另外,我强烈建议不要使用单字母变量名。它们难看,容易出错,而且没有信息。现代Fortran允许变量名长达63个字符。使用长而描述性的变量名并无害处。这是代码输出
$main
输入x0=0.11100000000000000 0.11100000000000000 0.11100000000000000
sze x0:3
尺寸x内ga:3
ga中的x为:0.11100000000000000 0.11100000000 0.111000000000
fn(x0)=0.33300000000000002
不要将fn声明为外部-给它一个合适的接口。毕竟,您正在使用假定的形状伪参数调用子程序,因此您需要告诉调用子程序,它正在传递的参数具有此属性。这是有效的。谢谢此外,感谢您提供有关现代Fortran最佳实践的提示。这可能是离题了,但是你知道哪里是寻找这些实践的好地方吗?前几篇关于“Fortran最佳实践”的文章很好。我不在这里直接链接到他们,因为它们通常不是永久的网络链接。官方Fortran语言的教程页面也不错,但这是一项正在进行的工作:@Kiyomine我刚刚偶然发现了这一页面,我同意他们的很多建议(如果不是全部的话):这很好。我希望这也能在将来帮助其他Fortran程序员。