使用接口

时间:2017-11-23 10:38:52

标签: fortran

我的代码如下:

使用接口块

在模块中声明该函数
    module my_subs
      implicit none

      interface
         function cross(a,b)
           integer, dimension(3) :: cross
           integer, dimension(3), intent(in) :: a, b
         end function cross
      end interface
    end module my_subs

    program crosstest
      use my_subs
      implicit none

      integer, dimension(3) :: m, n
      integer, dimension(3) :: r

      m = [1, 2, 3]
      n = [4, 5, 6]
      r = cross(m,n)
      write(*,*) r
    end program crosstest

    function cross(a,b)
      implicit none
      integer, dimension(3) :: cross
      integer, dimension(3), intent(in) :: a, b

      cross(1) = a(2)*b(3) - a(3)*b(2)
      cross(2) = a(3)*b(1) - a(1)*b(3)
      cross(3) = a(1)*b(2) - a(2)*b(1)
    end function cross

根据这个website,接口块的使用允许主程序和外部子程序适当地接口。但是,我测试了阵列大小情况的不同不匹配,我得到了以下结果:

  • 将第6行的dimension更改为2和4,无法编译代码;
  • 将第7行的dimension更改为2,可以编译代码并生成正确的输出;
  • 将第7行的dimension更改为4,无法编译代码;
  • 将第27行的dimension更改为2和4,代码可以编译并生成正确的输出;
  • 将第28行的dimension更改为2和4,可以编译代码并生成正确的输出;

我对我执行的不同场景感到困惑,因为我认为使用interface可以帮助我检测数组大小的任何不匹配。在这种情况下,使用cross(a,b)将函数my_subs移动到模块contains中是否更好?

2 个答案:

答案 0 :(得分:1)

你可以通过在函数交叉测试中检查接口,测试模块my_subs中声明的接口是否与cross认为其接口应该是什么函数匹配:

interface in function cross:
    module my_subs
      implicit none

      interface
         function cross(a,b)
           integer, dimension(3) :: cross
           integer, dimension(3), intent(in) :: a, b
         end function cross
      end interface
    end module my_subs

    program crosstest
      use my_subs
      implicit none

      integer, dimension(3) :: m, n
      integer, dimension(3) :: r

      m = [1, 2, 3]
      n = [4, 5, 6]
      r = cross(m,n)
      write(*,*) r
    end program crosstest

    function cross(a,b) result(res)
      use my_subs, only: check => cross
      implicit none
      integer, dimension(3) :: res
      integer, dimension(3), intent(in) :: a, b
      procedure(check), pointer :: test => cross

      res(1) = a(2)*b(3) - a(3)*b(2)
      res(2) = a(3)*b(1) - a(1)*b(3)
      res(3) = a(1)*b(2) - a(2)*b(1)
    end function cross

gfortran在你测试过的所有不匹配的情况下都会这样做。我不确定它应该:如果伪参数的TKR匹配,那么序列关联规则是否应该产生正确的过程调用?我还没有使用过子模块,但我认为它们可能与我的例子大致相同。

答案 1 :(得分:0)

当使用接口块在作用域内提供显式接口时(在本例中,在模块中,然后由主程序使用),程序员需要指定的接口与实际过程匹配。 1

首先,这些事情很愉快地匹配。更改过程的一个语句的函数结果或伪参数的大小而不是另一个语句的伪参数会导致不匹配。此类代码违反了Fortran标准。

通常,编译器不需要 来检测此违规。它可能会占用您的界面块on faith,或者它可能会做一些额外的工作来确定它是否应该相信您。后者是可能的,特别是如果外部过程在与接口块相同的文件中给出。您可能会看到一些与此相关的错误消息。

此外,如果给出了接口块,编译器将根据接口测试对过程的引用,而不是过程的实际定义。

程序员的一个失败是,如果实际参数与伪参数不兼容。这种情况是当伪参数是显式形状数组但实际参数小于伪参数时。 [让实际参数变大是不错的。]

这个问题是你的一个案例:

  interface
     function cross(a,b)
       integer, dimension(3) :: cross
       integer, dimension(4), intent(in) :: a, b  ! Dummy extent 4
     end function cross
  end interface

  print*, cross([1,2,3], [4,5,6])                 ! Actuals extent 3
  end

同样,编译器也没有义务为您注意到这一点。在可以检测到问题的情况下它很好。

现在,在另一种情况下,您声明函数结果是形状[4][2]的数组。但是您尝试将其分配给形状[3]的数组。那不会起作用。

总之,如果使用接口块为外部过程提供显式接口,请确保它是正确的。将外部程序转换为模块程序意味着编译器的责任,而不是您的责任,可以使正确的界面可见。

1 "匹配"这意味着接口块所声明的过程特征与过程的定义一致。函数结果和伪参数的范围是其中的一部分。一个定义纯粹的过程没有接口块说明它是纯粹的。