fortran - 包含声明

标签 fortran contains fortran90 subroutine

我不理解 的重要性包含 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/

相关文章:

c++ - dgesv 中的舍入错误?

java - 大数据的高效正则表达式,如果一个字符串包含一个词

javascript - 使用正则表达式的URL “starts with”?

c# - 在 List<DataRow> 中搜索?

fortran90 - 在 fortran 90 中打印函数名称

arrays - 定义返回数组的函数

parallel-processing - FORTRAN 中的 OpenMP 未运行预期的线程数

compiler-errors - 英特尔fortran编译错误 “This intrinsic function is invalid in constant expressions”

fortran - BLAS 函数在 Fortran90 中返回零

Fortran 90 如何编写不同长度的超长输出行