在 Fortran 中将“隐式无”放在哪里

Posted

技术标签:

【中文标题】在 Fortran 中将“隐式无”放在哪里【英文标题】:Where to put `implicit none` in Fortran 【发布时间】:2014-08-11 19:26:54 【问题描述】:

我需要把implicit none 放在每个函数和子程序中吗?

或者把它放在包含这些函数和子程序的模块的开头就足够了吗?

或者把它放在使用这些模块的程序的开头就足够了吗?

通过观察其他人的工作代码,implicit none 包含在所有这些地方。我不确定这是否是多余的,因为从子例程中删除 implicit none 仍然编译并产生相同的输出。

顺便说一句,我用的是gfortran fortran 90

【问题讨论】:

【参考方案1】:

implicit 语句(包括implicit none)适用于作用域单元。这样的事情被定义为

BLOCK 构造、派生类型定义、接口主体、程序单元或子程序,不包括其中的所有嵌套范围单元

这种“排除其中的所有嵌套范围单元”表明可能有必要/希望在模块中定义的每个函数和子例程(统称为过程)中都有implicit none。但是,在模块中包含的过程内部有一个基于 host 作用域单元的默认映射。因此,在模块中使用 implicit none 时,没有必要在包含的过程中使用它。

此主机范围单元规则同样适用于内部程序。这意味着主程序中的implicit none 涵盖了其中包含的所有程序;这同样适用于模块过程的内部程序。块构造也看到了这一点,而且其中之一甚至不允许使用 implicit 语句。

但是,外部函数/子例程不会从程序或模块继承隐式行为,并且模块不会从use 它们的程序/其他模块继承它。这显然是有道理的,因为隐式类型必须在编译时就知道,并且无论其最终用途如何,都必须得到很好的定义。

此外,不能将隐含规则从一个程序单元应用到它使用的模块,例如:

implicit none
use somemodule

end program

implicit 语句必须跟在所有 use 语句之后。

同样,子模块本身就是一个程序单元,与它的祖先不同。模块或子模块是扩展它的子模块的,而不是主机:主机范围单元规则不适用,子模块不继承从其父映射规则。如果子模块范围内没有 implicit 语句,则默认规则将在那里应用。

主机范围单元规则尤其不适用于接口主体。 IanH's answer 激发了这个例外,但这是一件足够重要的事情来重新强调。这引起了很多混乱。

module mod
 implicit none

  interface
    subroutine external_sub()
      ! The default implicit typing rules apply here unless
      ! there is an implicit statement, such as implicit none.
      ! Those from the module aren't in force here.
    end subroutine
  end interface

end module

关于从子例程中删除implicit none 的测试:如果代码对implicit none 有效,那么在没有该语句的情况下它必须有效且相同。在前一种情况下,所有实体都必须显式声明,因此在后一种情况下不会应用隐式规则。

【讨论】:

你能通过写一句话来稍微改进你的答案吗?提到程序中包含的函数/子例程与implicit none 中包含的模块中的函数/子例程完全一样?很好的答案。【参考方案2】:

如果您使用gfortran,您也可以简单地添加一个-fimplicit-none 参数。

请注意,这是特定于编译器的解决方案。其他广泛使用的编译器可能不支持此参数。例如,英特尔的ifort 将其视为未知选项而忽略。

【讨论】:

【参考方案3】:

这是一个基于对我有用的非正式答案。

我的 Fortran 代码位于两种类型的文件中 - 包含主程序的文件和包含单个模块的文件。在每种文件中,IMPLICIT NONE 都出现在“program foo”或“module foo”语句之后以及顶部的 USE 语句之后。它不会出现在子例程或函数中,因为那是多余的。

【讨论】:

我的帖子中有一个错误,现已修复。我把 IMPLICIT NONE 放在 USE 语句之后。我从不使用 INCLUDE 语句。【参考方案4】:

不,是(有点)和不。

每个程序单元一次(这与每个程序一次不同)在每个接口体中就足够了。

程序单元可以是主程序、模块、外部子程序(不在另一类程序单元的CONTAINS语句之后出现的函数或子程序子程序)、块数据程序单元或子模块。除非使用 IMPLICIT 语句另外指定,否则每个程序单元中的默认值是以 I-N 作为默认整数开头的事物的默认映射,其他所有事物都是默认实数。

同样的原则也适用于接口体——因为它们应该是在另一个程序单元中定义的过程的规范部分的快照。除非另有说明,否则其他程序单元将具有默认映射,因此除非另有说明,否则接口主体具有默认映射。

在程序单元内,内部子程序或模块子程序继承在其宿主中指定的任何隐式类型,在子程序本身内没有“本地”隐式语句的情况下。

IMPLICIT NONE 的冗余规范是无害的。您经常会看到将以前的外部子程序放入模块中的子程序。

【讨论】:

而且在现存的 FORTRAN 77 代码中也已经僵化了 ;)。视网膜上打孔卡的图像让我的眼睛流血了,但即使在 SO 上你也能找到很多。

以上是关于在 Fortran 中将“隐式无”放在哪里的主要内容,如果未能解决你的问题,请参考以下文章

在项目中将 useDispatch 和 bindActionCreators 放在哪里?

在 DDD 中将全局规则验证放在哪里

在 django 项目中将 service worker 和 manifest 放在哪里?

在领域驱动设计中将通用序列化类放在哪里?

在 AMD 模块中将 JavaScript 事件放在哪里?

在 Fortran 中逐行读取逗号分隔的文本文件