在子程序中调用子程序时出错

error when calling a subroutine within subroutine

您好,我尝试在下面创建一个最小的、完整的和可验证的示例代码来强调我收到的一条错误消息。错误是“(1) 处参数 'func0' 中的类型不匹配;将 REAL(4) 传递给了 COMPLEX(4)。

我在代码中指出了 (1) 中的错误消息所在。当我尝试在另一个子例程中调用一个子例程时,就会发生这种情况。

我最初尝试将隐式 none 添加到 Sub2 中,但随后我收到一条错误消息,指出 func0、func1 没有隐式类型。

我试图遵循这个 post 的逻辑:How to call and use a subroutine inside another subroutine in fortran?

Module Sample

integer :: n,m

contains 

subroutine Sub1(func0,func1)

implicit none

   complex, dimension(-10:10, -10:10), intent(inout) :: func0,func1
   complex, dimension(-10:10, -10:10) :: Deriv0,Deriv1


     do while (100 > 0.000001) 

        Deriv0 = Deriv(func0)
        Deriv1 = Deriv(func1)

     end do

end subroutine Sub1

subroutine Sub2(func3)
!implicit none : if this line is not commented out, I still get error messages saying func0,func1 do not have implicit types

   real,dimension(0:20), intent(inout) :: Func3

   call Sub1(func0,func1) !error message from here, this is line (1)

end subroutine  Sub2

function Deriv(func)
implicit none

complex, dimension(-10:10, -10:10) :: func, Deriv

   do n=-9,9
   do m=-9,9

     Deriv(n,m) = func(n+1,m)-2*func(n,m)

   end do
   end do

end function Deriv

End Module Sample

我该如何解决这个错误?谢谢

(免责声明:我实际上并不了解 Fortran。这个答案是 WAG。)

在您的 Sub2 子例程中,func0func1 都没有声明,它们不是参数。与代码的其他部分不同,Sub2 不包含 implicit none 指令,因此编译器假定您希望 func0 成为一个 REAL 变量,然后导致类型错误(因为 Sub1 需要一个 COMPLEX 变量)。

我无法告诉您如何解决此问题,因为您的代码从不在任何地方调用 Sub2,但大概您必须从某处获取两个 COMPLEX 变量才能传递给 Sub1 .

这里有一些我们关心的概念:范围;协会;和继承。

问题代码中有四个作用域单元:模块sample和三个过程(两个子例程和一个函数)。这些都是不同的,但它们之间共享一些信息。

首先查看 implicit 语句。在模块中没有 implicit 所以默认的类型规则适用于模块的范围单元。 (尽管模块中没有任何内容是隐式类型的——模块变量和函数都是显式声明的。)sub1deriv 每个都有 implicit none 所以类型规则(没有隐式类型)是那里写得很清楚。

sub2 中指定 implicit none 时,编译器会抱怨 func0func1 没有明确的类型声明;没有 implicit none 范围单元 sub2 继承其主机(模块)的类型规则,因此 func0func1 是真实的。

您可以在 another question and its answers 中阅读有关范围单位和键入规则的信息。综上,模块中放入implicit none

这种 func0func1 的类型将我们引向范围界定的另一个方面。 sub1sub2 是完全不同的范围单位。这两个子例程可以共享有关声明的知识的唯一方法是通过关联一种形式。

这里有两种关联形式:主机关联和参数关联。

宿主关联是每个子程序都可以访问变量nm。他们不引用那些变量,所以让我们忽略它们。主机关联还在 sub2 中给出了 sub1 的显式接口,它允许编译器抱怨类型不匹配。

sub2 的作用域单元中没有 func0func1 的显式声明。这是 implicit none 生效的错误;使用默认的隐式类型规则,它们是真正的标量变量或具有真正标量结果的函数。如果你想让它们成为复杂的数组,你只需要这样声明它们。

参数关联的产生方式如下。我们将 sub1 的虚拟参数与 sub2 的实际参数相关联。这里的关键是关联:两个不同的事物碰巧指向同一个对象。这两个过程不会共享任何未在每个过程中明确说明的内容。为了能够将实际参数与那些虚拟参数相关联,sub2 的范围内必须存在一些适当的东西。目前没有任何作用。


简而言之:您需要在 sub2 中适当声明 func0func1。这些可能是局部变量或伪参数,具体取决于您希望程序如何运行。