在 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 放在哪里?