是否需要接口块来编译Fortran?

时间:2019-02-15 13:39:09

标签: fortran gfortran

我正在尝试自学Fortran,并且一直在将多个文件链接在一起。在以下示例中,我一直在一个文件中编写程序,在另一个文件中编写函数,并在主程序中使用接口块来引用外部函数。

我正在测试接口块中需要多少信息,并意识到可以完全删除它。

我的程序:

    program test
        implicit none
        real :: x, y, func

        x = 3
        y = func(x)
        print *, y
    end program test

和功能文件:

    function func(x)
        implicit none
        real :: x, func
        func = x**3
    end function func

然后我使用gfortran -o test test.f90 func.f90对其进行编译,并且代码按预期工作。我的问题是,为什么我的程序文件中不需要包含接口块?这仅仅是一个好的实践问题,还是将func定义为一个实变量是否可以用作速记?我在Windows上,通过minGW安装了gfortran。

作为一个备用/相关的问题,如果我改为使用子例程:

    subroutine func(x,y)
        implicit none
        real :: x,y
        y = x**3
    end subroutine func

并将行y = func(x)更改为call func(x,y),然后代码将可以正常工作,而无需任何接口块或声明。为什么会这样?

3 个答案:

答案 0 :(得分:2)

此处主程序中的声明real :: func声明func是具有(默认)实际结果的函数。结果,该函数在主程序中具有接口,因此使用y = func(x)引用该函数是合法的。

在这种情况下,接口是隐式。这样,主程序就完全了解func的三件事:

  • 这是一个函数(具有该名称);
  • 它具有external属性;
  • 它有真实的结果。

对该功能的引用与此知识兼容。此外,您对函数的引用方式与函数本身的属性完全匹配。

同样,对于子例程,call func(x,y)会通过隐式接口准确地告诉主程序三件事:

  • 这是一个子例程(具有该名称);
  • 它具有external属性;
  • 需要两个实参。

这三件事再次与子例程的定义匹配,所以一切都很好。

那么,在这种情况下,您不需要接口块,因为隐式接口就足够了。

有时候,显式接口为required,并且在大多数(几乎所有情况)下,显式接口会更好。如您在其他问题和答案中所看到的,通常提供比使用接口块更好的方法来提供显式接口。

答案 1 :(得分:1)

  

为什么我的程序文件中不需要包含接口块?

从Fortran 90开始,定义可重用函数和子例程的推荐方法是使用模块。

module func_m
contains
    function func(x)
        implicit none
        real :: x, func
        func = x**3
    end function func
end module func_m

然后在use func_mimplicit nonegfortran -c func_m.f90gfortran -c test.f90之前的主程序中写入gfortran -o test test.o func_m.o

使用模块时,编译器将检查函数的参数类型。您也无需声明real :: func,因为声明是从模块中获取的。

当您将其编译为“简单”目标文件时,只要在目标文件中给出了该函数,编译器将直接调用任何名为func的函数而无需验证。

接口块是一种“中间”。您可以在程序文件中添加一个。这将迫使您在程序中遵循该声明。但这并不能防止在链接时链接到错误的函数:不能保证接口是正确的。如果您需要从不能使用模块的其他人那里调用C或FORTRAN 77代码,则该功能非常有用。

  

并更改行y = func(x)以调用func(x,y),然后代码将   无需任何接口块或声明即可正常工作。为什么会这样?

接口问题与功能vs子例程问题正交。

答案 2 :(得分:0)

在某些情况下,需要接口块。例如,如果被调用的子例程使用指针,可分配的或假定的形状数组(此列表不完整,请参阅标准以获取更多信息):

integer, pointer :: x(:,:)  ! pointer attribute
integer, allocatable :: x(:,:)  ! pointer attribute
integer :: a(:,:)           ! assumed shape array

指针/可分配对象的优点是被调用子例程可以将其分配给调用函数。假定形状数组会自动将尺寸转移到调用的子例程中。

如果使用其中任何一个,则如果没有显式接口,程序将崩溃。最简单的解决方案就像在另一个答案中所说:使用模块自动使接口正确。我们使用perl脚本自动提取接口以进行接口检查,而无需将代码重写为模块(避免长时间编译,直到所有编译器可靠地支持Fortran 2008子模块...)