Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 当传递函数名作为参数时,函数不接受数组作为输入_Fortran - Fatal编程技术网

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程序员。