Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Module Fortran中模块使用的模块的变量范围_Module_Include_Fortran_Fortran90 - Fatal编程技术网

Module Fortran中模块使用的模块的变量范围

Module Fortran中模块使用的模块的变量范围,module,include,fortran,fortran90,Module,Include,Fortran,Fortran90,我注意到父模块使用的(子)模块中的变量在主程序中可以通过父模块访问。这是一个概念,它清楚地将Fortran中的use语句与C/C++中的include语句区分开来。以下程序清楚地说明了这一概念 a、 f90 b、 f90 c、 f90 test.f90 请注意,我可以通过使用a_mod调用c_mod中的函数。请注意,除非遍历依赖项列表,否则我无法直接观察到c_mod可用 但是,在一个复杂的软件中,有没有一种简单的方法可以知道(比如说,使用IDE)某一行是否可以使用某个变量?在我看来,最好的办法是

我注意到父模块使用的(子)模块中的变量在主程序中可以通过父模块访问。这是一个概念,它清楚地将Fortran中的
use
语句与C/C++中的
include
语句区分开来。以下程序清楚地说明了这一概念

a、 f90

b、 f90

c、 f90

test.f90

请注意,我可以通过使用
a_mod
调用
c_mod
中的函数。请注意,除非遍历依赖项列表,否则我无法直接观察到
c_mod
可用


但是,在一个复杂的软件中,有没有一种简单的方法可以知道(比如说,使用IDE)某一行是否可以使用某个变量?

在我看来,最好的办法是避免使用笼统的
use
语句,尤其是对于大型且有时笨重的模块。相反,请仅通过
关键字指定要继承的模块实体,例如:

program main
   use a_mod, only : c, inc_c
   implicit none

   call inc_c
   write(*,*) c
end program main
这是可行的,但令人困惑,因为
a_mod
不是
c
inc_c
的真正所有者。因此,您应该尝试
使用实际声明实体的
实体,这将提供:

program main
   use c_mod, only : c, inc_c
   !   ^ This has changed
   implicit none

   call inc_c
   write(*,*) c
end program main
现在,任何阅读代码的人都清楚地知道哪些变量和子例程在范围内,以及它们来自何处


最后,这还有一个额外的好处,那就是降低了使用
c
而没有意识到它实际上是从
c\u mod
中固有的风险。如果不使用
隐式无
,这尤其是一个问题

正如Vladimir F在评论中所建议的,您可以使用模块中的
private
public
语句来解决此问题。如果您像这样重写模块:

module a_mod
  use :: b_mod

  private
  public :: a

  integer :: a
end module

module b_mod
  use :: c_mod

  private
  public :: b

  integer :: b
end module

module c_mod
  private
  public :: c, inc_c

  integer :: c = 10
contains
  subroutine inc_c
    c = c + 10
  end subroutine
end module
Namespace: A-Z: (UNKNOWN 0)
procedure name = test
  symtree: 'a'           || symbol: 'a'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(a_mod))
  symtree: 'a_mod'       || symbol: 'a_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(a_mod))
  symtree: 'b'           || symbol: 'b'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(b_mod))
  symtree: 'b_mod'       || symbol: 'b_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(b_mod))
  symtree: 'c'           || symbol: 'c'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(c_mod))
  symtree: 'c_mod'       || symbol: 'c_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(c_mod))
  symtree: 'inc_c'       || symbol: 'inc_c'                             <---        
    type spec : (UNKNOWN 0)                                             <---
    attributes: (PROCEDURE MODULE-PROC  USE-ASSOC(c_mod) SUBROUTINE)    <---
  symtree: 'test'        || symbol: 'test'         
    type spec : (UNKNOWN 0)
    attributes: (PROGRAM PUBLIC  SUBROUTINE)

在这种情况下,每个模块开头的语句
private
表示默认情况下不会导出模块中声明的数量。现在,您必须通过添加
public
语句,明确声明在
使用该模块时可用的变量和子例程。(这也可以使用语法
integer,public::c=10
在一行中完成)这种做法可以防止
c_mod
变量从
b_mod
中泄漏出来,以此类推。

虽然不像IDE那样是inituitve,gfortran可以通过附加
-fdump fortran original
来打印导入的符号列表(或
-fdump parse tree
)选项。为此,我们首先生成*.mod文件,如下所示:

gfortran -c {c,b,a}.f90
并将所需的源代码编译为

gfortran -fdump-fortran-original -c test.f90
然后,我们得到一个导入符号列表,如下所示:

module a_mod
  use :: b_mod

  private
  public :: a

  integer :: a
end module

module b_mod
  use :: c_mod

  private
  public :: b

  integer :: b
end module

module c_mod
  private
  public :: c, inc_c

  integer :: c = 10
contains
  subroutine inc_c
    c = c + 10
  end subroutine
end module
Namespace: A-Z: (UNKNOWN 0)
procedure name = test
  symtree: 'a'           || symbol: 'a'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(a_mod))
  symtree: 'a_mod'       || symbol: 'a_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(a_mod))
  symtree: 'b'           || symbol: 'b'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(b_mod))
  symtree: 'b_mod'       || symbol: 'b_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(b_mod))
  symtree: 'c'           || symbol: 'c'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(c_mod))
  symtree: 'c_mod'       || symbol: 'c_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(c_mod))
  symtree: 'inc_c'       || symbol: 'inc_c'                             <---        
    type spec : (UNKNOWN 0)                                             <---
    attributes: (PROCEDURE MODULE-PROC  USE-ASSOC(c_mod) SUBROUTINE)    <---
  symtree: 'test'        || symbol: 'test'         
    type spec : (UNKNOWN 0)
    attributes: (PROGRAM PUBLIC  SUBROUTINE)
然后,输出也相应地简化:

Namespace: A-Z: (UNKNOWN 0)
procedure name = test
  symtree: 'a_mod'       || symbol: 'a_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(a_mod))
  symtree: 'inc_c'       || symbol: 'inc_c'        
    type spec : (UNKNOWN 0)
    attributes: (PROCEDURE MODULE-PROC  USE-ASSOC(c_mod) SUBROUTINE)
  symtree: 'test'        || symbol: 'test'         
    type spec : (UNKNOWN 0)
    attributes: (PROGRAM PUBLIC  SUBROUTINE)

因此,尽管我从未为此目的使用过此选项,但它可能对OP的目的有所帮助(如果真的需要).

每个IDE都是不同的。这无法真正回答。一些IDE可能提供此功能,而另一些可能不提供。许多Fortran程序员根本不使用任何IDE。请注意,Fortran使用
私有
公共
和仅
的方式具有更好的可访问性。我认为这并不能有效地解决问题。重点是在
b_mod
中使用
c
inc_c
中的
c_mod
。将实体设置为私有可以防止这种情况。我不是建议您在任何地方都将条目设置为私有。我是建议您在
c_mod
中将它们设置为公共(以便在
使用::c_mod
时导入),但在
b_mod
中设置相同的变量
private
(以便在
use::b_mod
use::a_mod
时不会导入这些变量)请注意,我在我的
c_mod
版本中明确表示
public::c,inc_c
,而您的评论表明您认为我将这些设置为
private
。我现在明白了,这解决了问题,您是对的。
Namespace: A-Z: (UNKNOWN 0)
procedure name = test
  symtree: 'a'           || symbol: 'a'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(a_mod))
  symtree: 'a_mod'       || symbol: 'a_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(a_mod))
  symtree: 'b'           || symbol: 'b'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(b_mod))
  symtree: 'b_mod'       || symbol: 'b_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(b_mod))
  symtree: 'c'           || symbol: 'c'            
    type spec : (INTEGER 4)
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(c_mod))
  symtree: 'c_mod'       || symbol: 'c_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(c_mod))
  symtree: 'inc_c'       || symbol: 'inc_c'                             <---        
    type spec : (UNKNOWN 0)                                             <---
    attributes: (PROCEDURE MODULE-PROC  USE-ASSOC(c_mod) SUBROUTINE)    <---
  symtree: 'test'        || symbol: 'test'         
    type spec : (UNKNOWN 0)
    attributes: (PROGRAM PUBLIC  SUBROUTINE)
program test
  use a_mod, only: inc_c
  implicit none

  call inc_c
end program
Namespace: A-Z: (UNKNOWN 0)
procedure name = test
  symtree: 'a_mod'       || symbol: 'a_mod'        
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(a_mod))
  symtree: 'inc_c'       || symbol: 'inc_c'        
    type spec : (UNKNOWN 0)
    attributes: (PROCEDURE MODULE-PROC  USE-ASSOC(c_mod) SUBROUTINE)
  symtree: 'test'        || symbol: 'test'         
    type spec : (UNKNOWN 0)
    attributes: (PROGRAM PUBLIC  SUBROUTINE)