【Fortran】过程设计之二(模块MODULE)

目录


前言

子例程中,主程序通过带有参数列表的调用来实现与不同子例程的数据交换。
除了参数列表,在Fortran中还可以通过 模块MODULE 来交换数据。

模块是一个独立编译的程序单元,它包含了在程序单元间共享的数据的类型定义和初始值。


Fortran模块(MODULE)

1) 使用方式

常规用途是没有输入输出参数,仅用于共享数据,以供主程序、子例程等调用。
定义语句格式

MODULE module_name   ! 定义模块名
SAVE
	(声明变量部分)
	...
RETURN
END MODULE [ module_name ]  ! []表示可选

注意事项

  • module_name由字母、数字和下划线组成 ,最大长度可达63个字符,第一个字符为字母;
  • 仅用于声明变量,没有计算执行部分;
  • SAVE语句能够确保模块中声明的数据值在不同过程中引用时会被保留,应尽量留有这语句;
  • 由于模块中的变量是共享的,能够直接调用具体变量,因此在主程序、子例程等程序单元中,如果调用了该模块,定义局部变量时不能与模块中变量同名,否则会出错。

调用语句格式
USE module_name

注意事项

  • USE语句相当于是继承模块中的变量,因此变量名不能重复;
  • 为了在特定程序单元中访问数据,应该把USE语句放置在PROGRAMSUBROUTINEFUNCTION语句后面的第一句位置处。

2) 模块示意

MODULE share_data
IMPLICIT NONE
SAVE
INTEGER , PARAMETER :: num_vals = 5 , PI = 3.141592
REAL , DIMENSION(num_vals) :: values
END MODULE share_data

3) 模块过程(显式接口)

在模块中定义子例程、函数等过程被称为模块过程。这些过程在模块中被完整定义,并使用包含模块名的USE语句使得定义的模块过程在程序单元中有效。如对于模块子例程:

MODULE module_name   ! 模块
IMPLICIT NONE
...(声明共享的数据)
CONTAINS
	SUBROUTINE subroutine_name( parameter )   ! 子例程
	...(声明、执行部分)
	END SUBROUTINE subroutine_name
END MODULEmodule_name
PROGRAM main_name    ! 主程序
USE module_name
...
CALL subroutine_name( parameter )  
...
END PROGRAM main_name

注意事项

  • CONTAINS语句是告诉编译器后面的语句被包含在过程中,不能缺少
  • 模块中的过程必须要接受模块中声明的任何数据对象;
  • 必须先调用了模块,才能调用模块中的过程。

问:既然子例程能够在外部独立调用,为何多此一举?
答:原因是在模块中编译一个过程,当USE该模块时,模块中定义的过程接口的所有细节对编译器都是有用的,编译器可以自动检测过程调用中的参数个数、类型、是否是数组、以及每个参数的INTENT属性,可以通过检查接口来确保正确使用过程。

上述,一个在模块内编译和用USE访问的过程称为带有显式接口(explicit interface)。

相对地,不在模块内的过程称为带有隐式接口(implicit interface)。隐式接口的使用前提条件是:保证过程定义形参和过程调用实参的变量一一对应(大小、类型、结构等信息)。一旦出错,程序会终止(不返回详细错误信息),有的甚至能成功运行但与预想相违背。如下例子:

隐式接口

PROGRAM bad_call   ! 主程序,错误示范
IMPLICIT NONE
REAL :: x = 1.

CALL bad_argument( x )

END PROGRAM bad_call
SUBROUTINE bad_argument ( i )    ! 子例程
IMPLICIT NONE
INTEGER :: i

WRITE(*,*) ' i = ' , i
END SUBROUTINE bad_argument

相应结果为:

i =   1065353216  ! 实参1.的内存地址

子例程定义的形参类型为整型,主程序调用子例程所输入的实参是实型,结果是程序传递实型参数的地址给了子例程,但子例程缺把它当做整型来处理,结果完全错误。

显式接口

PROGRAM bad_call   ! 主程序
USE mod1
IMPLICIT NONE
REAL :: x = 1

CALL bad_argument( x )

END PROGRAM bad_call
MODULE mod1      ! 模块 
CONTAINS
    SUBROUTINE bad_argument ( i )    ! 模块子例程
    IMPLICIT NONE
    INTEGER :: i

    WRITE(*,*) ' i = ' , i
    END SUBROUTINE bad_argument
END MODULE mod1

运行,弹出报错:

error #6633: The type of the actual argument differs from the type of the dummy argument.   [X]		

这是显式接口的优势,检查过程的变量数据是否匹配,例子中的报错显示实参x与形参的类型不一致。

上一篇:kudu安装过程中可能出现的问题


下一篇:278. First Bad Version 折半查找,分治法