我不理解 的重要性包含 fortran 90 中的语句
例如
PROGRAM BLABLA
IMPLICIT NONE
INTEGER :: i,j,k
i = 1; j = 1;k =1
PRINT *, i,j,k
CALL ABC(i,j,k)
PRINT *, i,j,k
CONTAINS
SUBROUTINE ABC(r,s,t)
IMPLICIT NONE
INTEGER, INTENT(IN) :: r,s
INTEGER, INTENT(OUT) :: t
t = r + s
END SUBROUTINE ABC
END PROGRAM BLABLA
一种是在主程序之外定义子程序。我理解对于函数,需要指定函数的类型,但对于子例程则不需要。我有兴趣了解这样做是否还有其他注意事项?
PROGRAM BLABLA
IMPLICIT NONE
INTEGER :: i,j,k
i = 1; j = 1;k =1
PRINT *, i,j,k
CALL ABC(i,j,k)
PRINT *, i,j,k
END PROGRAM BLABLA
SUBROUTINE ABC(r,s,t)
IMPLICIT NONE
INTEGER, INTENT(IN) :: r,s
INTEGER, INTENT(OUT) :: t
t = r + s
END SUBROUTINE ABC
最佳答案
在您的第一个和第二个版本中尝试更改行
CALL ABC(i,j,k)
到
CALL ABC(i,j)
看看会发生什么,首先是在编译时,其次是在运行时。
当您完成此操作并报告您的发现后,我可以将其转化为正确的答案。
好的,这就是答案,其中大部分你已经想通了:
在过去,在 Fortran 90 之前,FORTRAN(当时每个人都在喊这个名字)程序在单独的“单元”中编译是很常见的(现在仍然如此)。在您的第二个版本中,程序和子例程位于不同的单元中并分别编译。编译器没有可用的信息来检查对子例程的调用是否与子例程签名匹配——这留给程序员检查。错误地调用子例程,几乎任何事情都可能发生——如果你很幸运,程序崩溃或产生明显错误的结果,如果你不走运,它会产生不是明显错误但仍然错误的结果。
如果您在程序单元范围内包含子程序的源代码,并使用
contains
部分,就像在您的程序的第一个版本中一样,编译器将为子例程创建一个接口(interface),并且可以检查对子例程进行的任何调用在形式上是否正确。因此,您发现编译失败。让编译器为子程序生成接口(interface)的另一种方法,这些方法也适用于函数,是将它们放入一个模块中,
use
程序中的模块。您会在其他 Qs 和 As here on SO 中找到许多如何执行此操作的示例。将子程序放入模块与将其包含在
contains
中并不完全相同。部分。在 contains
子程序可以使用程序中声明的变量,而无需通过子程序的参数列表。这被认为是糟糕的编程实践而令人不悦,但您确实会在野外遇到它。
关于fortran - 包含声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35808053/