【问题标题】:How to explicitely use inherited variables in Fortran?如何在 Fortran 中显式使用继承变量?
【发布时间】:2017-09-12 13:32:51
【问题描述】:

我对模型/变量使用的最佳实践有疑问:

假设我有一个包含一些变量/参数定义的模块和一些使用这些变量的子例程。

我不需要在子例程中显式使用这些变量,因为它们是从父模块继承的 - 但这样做会更好吗?

例子:

module test
implicit none

integer, parameter :: a = 1
real               :: x

contains

subroutine idk(y,z)
  real, intent(in)  :: y
  real, intent(out) :: z

  if(a .eq. 1) then
    z = x*y + 5.
  else 
    z = x*y - 5.
  end if
end subroutine idk

end module test

上面的例子应该可以正常工作,但添加会更好

use test, only: a,x

到子程序idk的声明部分?

在我的推理中,这里有两个要点:

1) Pro:显式添加这一行让我很容易看到子程序中实际需要哪些变量。 在许多情况下,模块包含相当多的变量,但每个子例程中只需要几个变量。因此,为了更好地理解,添加这一行将是有益的。

但是

2) 相反:在相当多的情况下,需要很多上面声明的变量/参数(有时编号超过 100 个参数)。在子例程的开头显式使用这些只会不必要地使代码混乱,降低代码的可读性。

如果只需要包含几个变量,第 1 点最重要,而第 2 点只有在需要包含许多变量时才重要。但我认为为少数变量做一件事而为许多变量做另一件事是愚蠢的 - 一旦你选择了一个约定,你应该坚持它恕我直言......

有没有这方面的最佳做法?

补充: 或者,可以将子例程声明为

subroutine idk(b,w,y,z)

然后将其称为idk(a,x,y,z)

一方面,如果我以后决定要将idk 与其他变量一起使用,这会给我更大的灵活性。

另一方面,如果我稍后更改某些内容,也会增加出错的风险(例如,我意识到我不需要参数a 作为条件,而是参数c。在第一种情况下,我只是简单地在子程序中切换出a -> c。但在最后一种情况下,我需要将每个调用更改为idk(c,...)。如果这些调用很多,这很容易出错)

非常感谢您的意见!谢谢!

【问题讨论】:

  • 另一种选择是将参数放在单独的模块中。
  • 我总是谨慎处理主机关联,并在源代码中记录它。请注意,即使您决定将必要的变量作为 args 传递给内部过程,主机变量仍可能被“意外”访问/修改。我认为这比忘记将变量传递给外部子程序更糟糕,因为在这种情况下,您会立即看到错误。
  • 我考虑将参数放在单独的模块中。我遇到的问题是:代码很大,我有很多参数。通过将变量声明与使用它们的主要例程放在一起,它似乎组织得很好。外包它们基本上会使模块的数量增加一倍(除非我把它们都放在一个大的控制文件中,这可能会相当混乱,因为它确实很大),使得找到我需要的东西变得更加困难。但现在我很担心这会给我带来麻烦。如何确保不会无意中修改主机关联变量?

标签: variables module fortran


【解决方案1】:

绝对没有理由use 当前正在定义的模块。这是非法的。如果模块之前编译过,编译器可以找到.mod文件,但是文件,但除此之外它是错误的。

你应该期待错误,例如

    ifort -c assoc.f90
assoc.f90(10): error #6928: The module-name on a USE statement in a program unit cannot be the name of any encompassing scoping unit.   [TEST]
  use test
------^

模块子程序通过主机关联从主机模块获取变量,use语句用于使用关联。这是两种不同的东西,不应混为一谈。

如果您想避免使用全局变量,请将它们作为参数传递。这是一般建议。什么是最好的取决于每个案例和程序员,不能一概而论。

【讨论】:

  • 感谢您的回答!由于这个原因,我从来没有遇到过 gfortran 的编译器问题(即使没有 .mod 文件),所以我只是假设两者都是允许的。我假设主机关联取代使用关联?所以如果我在我的模块testuse some_mod, only: some_variable,那么我不需要(也不应该)在包含的子例程idk 中再次这样做?
  • 可以在子例程中再次执行此操作,但您不必这样做。前提是它引用了不同的模块。
  • Gfortran 给了我Fatal Error: Can't open module file 'test.mod' for reading at (1): No such file or directory
  • 所以我可以输入module test \ use some_mod, only: some_variable \ ... \ contains \ subroutine idk(y,z) \ use some_mod, only: some_variable \ ... 这会被允许吗? some_variable 不是已经与idk 主机关联,因为它现在“包含”在test 中吗?
  • 是的,这是允许的。我不确定确切的标准术语,但肯定是允许的。一旦你在子例程中使用关联符号,你就会隐藏它在主机模块中的任何定义。
猜你喜欢
  • 2023-02-09
  • 1970-01-01
  • 1970-01-01
  • 2011-12-08
  • 1970-01-01
  • 2019-12-15
  • 2014-02-06
  • 2016-07-15
  • 1970-01-01
相关资源
最近更新 更多