Module Fortran中模块使用的模块的变量范围
我注意到父模块使用的(子)模块中的变量在主程序中可以通过父模块访问。这是一个概念,它清楚地将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)某一行是否可以使用某个变量?在我看来,最好的办法是
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)