第六章: 过程和模块

程序单元结构

6.1.1 概述

FORTRAN程序应由一个主程序单元和若干个过程程序单元组成。编程前应先作结构化分析,把问题分解为若干个子功能,每个子功能编成一个独立的程序单元,称为过程程序单元。再编一个主程序单元,控制整个解题过程。在主程序单元中用简练的形式调用每个过程,每次调用就是执行该过程单元,完成该子功能,从而最终完成解题任务。本章介绍F90中的程序单元、过程、范围、模块等概念。

F90中,共有四种程序单元:

*           主程序

*           过程或辅程序

*           块数据单元

*           模块

其中模块是F90新增加的一种程序单元。通过使用模块,可以方便地共享数据和过程。各种程序单元中,除主程序外,各程序单元可以被其他程序单元甚至自身调用。一个程序单元不需要包含可执行语句。包含内部子程序或函数的程序单元称为宿主程序。下表是对这四种程序单元类型的定义:

程序单元

定义

主程序

主程序是程序开始执行的标志,其第一条语句不能是SUBROUTINEFUNCTIONMODULEBLOCK DATA。主程序可以用PROGRAM语句作为第一条语句,但不是必需的

过程

子程序或函数

块数据单元

在命名的公共块中提供变量初始值的程序单元

模块

包含数据对象定义、类型定义、函数或子程序接口和其它程序可访问的函数或子程序

程序单元之间的关系有:

*           联合:这种机制允许不同的程序单元共享变量,从而不用重新定义变量就可以以不同的名字处理同一数据。

*           范围:它描述的是一个名称(或者是全局的或者是局部的)作用的范围。

6.1.2 主程序

程序的执行始终是开始于主程序的第一条可执行语句,所以每个完整的Fortran程序必须有且仅有一个主程序。其形式为:

[PROGRAM [程序名]]

[说明部分]

[可执行部分]

[CONTAINS

内部过程]

END [PROGRAM[程序名]]

可以看到,主程序单元中允许包含内部过程。主程序名和外部过程名和公共块名都被认为是全局名称。全局名称在一个程序中必须是唯一的。

例:PROGRAM MAIN

REAL X(10),A(10,10),B(10)   !说明部分

CALL GAUSS(A,B,X)           !执行部分,调用内部过程GAUSS

CONTAINS

SUBROUTINE GAUSS(R,S,T)     !内部过程的开始

END SUBROUTINE GAUSS        !内部过程的结束

EHD PROGRAM MAIN

下图显示的是一个F90程序的标准结构。每个框都可以是一个独立的源文件:


6.1.3 过程

a)    外部过程

如果过程是一个独立于主程序单元的程序单元,它就是外部过程。外部过程也可以通过非Fortran语言(通常是汇编语言)来定义。外部过程的形式有两种:

外部函数  FUNCTION语句

[说明部分]

[可执行部分]

[CONTAINS

内部过程]

END [FUNTION函数名]

外部子程序SUBROUTINE语句

[说明部分]

[可执行部分]

[CONTAINS

内部过程]

END [SUBROUTINE子程序名]

b)    内部过程

内部过程是包含于外部过程、模块或主程序单元之中的程序单元。在宿主程序单元中,以CONTAINS语句把内部过程与其他部分分开。内部过程也具有两种形式:

内部函数  FUNCTION语句

[说明部分]

[可执行部分]

END [FUNTION函数名]

内部子程序SUBROUTINE语句

[说明部分]

[可执行部分]

END [SUBROUTINE子程序名]

注意内部过程中不能再包含内部过程,即F90不是过程嵌套式语言。

c)    内在过程

内在过程是Fortran含于编译器程序库中的过程,它不需任何其它声明或说明即可使用。F90中定义了113个内在过程,它们为科学计算提供了极大方便,内在过程除了第一章中介绍的部分内在函数和第五章中介绍的部分数组函数外,还有其他一些内在函数及内在子程序,其具体使用方法请查看Visual Fortran的联机帮助。内在过程共分为四类:

1、查询函数:它们的返回值是根据变元的性质而非变元的取值。

2、 基本过程:由标量变元指明的基本过程,但可以用标量或数组实元进行调用。有许多函数是这种基本函数,并有一种基本内在子程序(MVBITS)。如果变元是标量,则结果也是标量。如果变元是数组,则对数组的每个元素施加过程,其结果是与变元形状相同的数组。例如,a是数组的话,则b=sin(a)也是数组。

3、 变换函数:其变元是数组,但过程不施加于每个元素,而是把变元变换成另一数组。

4、 非基本过程:只能以标量实元进行调用,除了MVBITS以外的所有内在子程序都是非基本过程。

如果要用内在过程名作为其它过程的实元,需要用INTRINSIC语句加以声明。

6.1.4 块数据

块数据单元是一种为有名公用块中的变量定义初始值的一种程序单元,它只包含数据声明和初始值,不包含可执行语句。其一般形式为:

BLOCK DATA[块数据名]

[说明部分]

END [BLOCK DATA[块数据名]]

变量一般由DATA语句来初始化。公共块中命名的变量只能在块数据单元或某个过程中初始化一次,或只能由所有的过程完全一致地初始化。更好的编程法是用模块而不是块数据单元来声明和初始化变量。

在块数据单元的说明部分,不能包含ALLOCATABLEAUTOMATICEXTERNALINTENTOPTIONALPRIVATEPUBLIC等属性说明符。

例:BLOCK DATA BLKDAT

INTEGER S,X

LOGICAL T,W

DOUBLE PRECISION U

DIMENSION R(3)

COMMON/AREA1/R,S,U,T/AREA2/W,X,Y

DATA R/1.0,2*2.0/,T/.FALSE./,U/0.214537D-7/,W/.TRUE./,Y/3.5/

END BLOCK DATA BLKDAT