【问题标题】:Contains statement包含声明
【发布时间】:2016-06-18 21:31:18
【问题描述】:

我不理解 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

一种是在主程序之外定义子程序。我理解对于函数,需要指定函数的类型,但对于子例程则不需要。我有兴趣了解这样做是否还有其他注意事项?

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

【问题讨论】:

    标签: fortran contains fortran90 subroutine


    【解决方案1】:

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

    CALL ABC(i,j,k)
    

    CALL ABC(i,j)
    

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

    当您这样做并报告您的发现后,我可以将其转化为正确的答案。

    好的,这就是答案,其中大部分你已经想通了:

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

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

    让编译器为子例程生成接口的另一种方法,这些方法也适用于函数,是将它们放入模块中,use 将模块放入程序中。您会在其他 Qs 中找到许多关于如何执行此操作的示例,以及在 SO 上的 As here。

    将子例程放入模块与将其包含在contains 部分中并不完全相同。在contains 部分中,子例程可以使用程序中声明的变量,而无需通过子例程的参数列表传递它们。这被认为是糟糕的编程实践而令人不悦,但您确实会在野外遇到它。

    【讨论】:

    • 当我没有 CONTAINS 时,它会编译,但会给出 j 的错误答案(任意大)。当我有 CONTAINS 时,它不允许我编译。所以我猜 CONTAINS 作为参数的额外检查。到目前为止,我正在编写没有 CONTAINS 的代码。如果使用 CONTAINS 编译相同的代码,我可以确保其他代码就参数而言是正确的。更准确地说,如果在任何代码中,没有传递参数(但作为全局变量保存在 MODULES 中),两者是否相同?
    猜你喜欢
    • 2012-12-04
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    • 2012-01-28
    • 2011-12-12
    • 2016-11-05
    • 2021-10-06
    • 1970-01-01
    相关资源
    最近更新 更多