包含陈述

Vai*_*han 7 fortran contains subroutine fortran90

我不了解FORtran 90 中CONTAINS语句的重要性

例如

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
Run Code Online (Sandbox Code Playgroud)

一种是通过在主程序之外定义子例程。我知道对于函数来说,需要指定函数的类型,但是对于子例程则不需要。我有兴趣了解这样做是否还有其他警告?

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
Run Code Online (Sandbox Code Playgroud)

Hig*_*ark 5

在您的第一个版本和第二个版本中,尝试更改行

CALL ABC(i,j,k)
Run Code Online (Sandbox Code Playgroud)

CALL ABC(i,j)
Run Code Online (Sandbox Code Playgroud)

看看会发生什么,首先是在编译时,其次是在运行时。

当您完成此操作并报告您的发现后,我可以将其转变为正确的答案。

好的,这就是答案,您已经弄清楚了其中的大部分内容:

在Fortran 90之前的过去,将FORTRAN(当时每个人大喊大叫)程序编译为单独的“单元”(现在仍然是)是很常见的。在第二个版本中,程序和子例程位于单独的单元中,并且分别进行编译。编译器没有可用信息来检查对子例程的调用是否与子例程签名相匹配-留给程序员检查。错误地调用该子例程,几乎任何事情都可能发生-如果您很幸运,该程序将崩溃或产生明显错误的结果,如果您很不幸,它将产生并非显而易见的错误但仍然错误的结果。

如果将子例程的源代码包括在程序单元的范围内,并使用该contains部分,如在程序的第一个版本中一样,则编译器将为该子例程创建一个接口,并可以检查对子例程的任何调用在形式上是正确的。因此,您发现编译失败。

让编译器生成子例程接口的另一种方法,这些方法也适用于函数,就是将它们放入模块中,并将其放入use程序中的模块中。您将在SO的其他《问与答》中找到许多如何执行此操作的示例。

将子例程放入模块中与将其包含在contains部分中并不完全相同。在本contains节中,子例程可以使用程序中声明的变量,而无需通过子例程的参数列表传递变量。由于不良的编程习惯,人们对此并不满意,但是您确实会在野外遇到它。