Function Fortran中模块、子程序和函数的正确使用

Function Fortran中模块、子程序和函数的正确使用,function,module,fortran,fortran90,subroutine,Function,Module,Fortran,Fortran90,Subroutine,我最近了解了在Fortran程序中添加函数时的接口块。一切工作都很好,很整洁,但现在我想在接口块中添加第二个函数 这是我的接口块: interface function correctNeighLabel (A,i,j,k) integer :: correctNeighLabel integer, intent(in) :: i,j,k integer,dimension(:,:,:),intent(inout) :: A end function

我最近了解了在Fortran程序中添加函数时的接口块。一切工作都很好,很整洁,但现在我想在接口块中添加第二个函数

这是我的接口块:

interface
    function correctNeighLabel (A,i,j,k)
    integer :: correctNeighLabel
    integer, intent(in) :: i,j,k
    integer,dimension(:,:,:),intent(inout) :: A
    end function

    function correctNeighArray (B,d,e,f)
        character :: correctNeighArray
    integer, intent(in) :: d,e,f
    character, dimension(:,:,:),intent(inout) :: B
    end function
end interface
在我看来,这可能不是最好的选择

我研究过子程序,但我不太相信它是正确的解决方案。我所做的是相对简单的,我需要将参数传递给子例程,但是我看到的所有子例程都是a)复杂的(即对于函数来说太复杂),b)不接受参数。它们的行为就好像它们在不传递变量的情况下操纵变量一样

我没有真正正确地研究模块,但从我所看到的情况来看,它不是正确的使用方法


我应该在什么时候使用哪一个?我该如何最好地使用它?

模块始终是正确的使用方式;-)

如果您有一个非常简单的F90程序,您可以在“包含”块中包含函数和子例程:

 program simple
   implicit none
   integer :: x, y
   x = ...
   y = myfunc(x)
 contains
   function myfunc(x) result(y)
     implicit none
     integer, intent(in)  :: x
     integer              :: y
     ...
   end function myfunc
 end program
然后,函数/子例程的接口将在程序中已知,不需要在接口块中定义

对于更复杂的程序,您应该将所有函数/子例程保留在模块中,并在需要时加载它们。因此,您也不需要定义接口:

 module mymod
   implicit none
   private
   public :: myfunc
 contains
   function myfunc(x) result(y)
     implicit none
     integer, intent(in)  :: x
     integer              :: y
     ...
   end function myfunc
 end module mymod

 program advanced
   use mymod, only: myfunc
   implicit none
   integer :: x, y
   x = ...
   y = myfunc(x)
 end program advanced

模块和程序可以(实际上应该)在单独的文件中,但模块必须在实际程序之前编译。

附议并扩展已经说过的内容。最好将您的过程(子例程和函数)放入模块中并“使用”它们,因为您可以轻松地自动检查接口的一致性。其他方法也有缺点。如果使用接口块定义接口,则需要维护三件事,而不是两件事:接口、过程本身和调用。如果你做了一个改变,那么所有三个都必须修改以保持一致。如果使用一个模块,只需更改两个。使用接口块的一个原因是,如果您无法访问源代码(例如,预编译库)或源代码使用另一种语言(例如,您通过ISO C绑定使用C代码)


“包含”方法的缺点是包含的过程继承父程序的所有局部变量。。。这不是很模块化,如果您忘记了这个“功能”,可能会非常混乱;让我在一点上再充实一点——如果模块是未来的发展方向(它们确实是),那么接口到底是用来做什么的呢

对于模块中的函数和子例程,任何
使用的
s模块都可以自动看到这些接口;接口是在编译模块时生成的(除其他外,这些信息会进入编译模块时生成的.mod文件)。所以你不需要自己写。类似地,当您使用
包含
ed子程序时(与MSB一致,我发现这更容易混淆,但更有用-它们被认为是或比外部子例程更好),主程序可以显式地“查看”接口,而不需要您为其编写

接口块用于无法执行此操作的情况—编译器无法为您生成显式接口的情况,或者您希望获得与给定内容不同的内容的情况。一个例子是在Fortran 2003中使用时。在这种情况下,Fortran代码链接到某个C库(比如说),无法为您生成C例程的正确Fortran接口——您必须自己编写接口块来完成


另一个例子是,当您已经知道子例程的接口时,但是当您想要创建一个新接口来“隐藏”后面的子例程时-例如,当您有一个例程操作(比如)整数,一个例程操作实数,您希望能够对其中任何一个调用相同的例程名称,并让编译器根据参数对其进行排序。这种结构被称为fortran90,并且自fortran90以来一直存在。在这种情况下,您可以显式地为这个新的通用例程创建一个接口,并在该接口块中列出“真实”例程的接口。

在Fortran中,在顶部代码块中是“character”而不是“char”,您不启动子例程或任何名为
mysub
的程序,而是关闭它。允许这样做吗?在第二个编码块中执行相同的操作。这些应该是
结束函数myfunc
行吗?所以我可以把我的函数转换成一个新的模块,它应该像那样工作,我可以调用函数,就好像它们在主程序中一样?我想我明白这是怎么回事了。非常感谢。“函数myfunc”应该以“end function myfunc”结尾——固定。如果包含这些过程的模块也有
隐式无
,那么在每个包含的过程中是否有必要使用
隐式无
?+1当然,接口是有用的,我倾向于尽可能多地使用泛型过程。