版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第13章 Fortran指针 指针是现代程序设计语言中一个非常重要的概念,指针的应用能够大大加强程序语言的功能。Fortran 90以前的Fortran标准中没有提供指针这种数据类型,在Fortran 90标准中对这种现象进行了重大的改进,引入了指针的概念。 但是值得注意的是,标准Fortran中的指针与C语言中的指针并不完全相同。标准Fortran中的指针并不代表一个变量在内部存储单元中的地址,而是代表这个变量的别名。实质上标准Fortran中的指针相当于C语言中的引用。本章将介绍Fortran指针的概念与应用。13.1 指针的基本概念 在没有引入指针概念之前,Fortran中对变量的使用都
2、是通过变量的名字直接进行的,程序中每个变量的名字都必须是惟一的。那么同一个变量是否可以取不同的名字呢?Fortran 90/95中的指针,正是用来给变量起别名的。通过指针,同一个变量存储单元可以通过多个变量名来进行访问。13.1.1 定义指针Fortran语言中,要将一个变量名定义成指针,可以采用如下的语法形式来进行:类型说明, POINTER : 指针变量名列表其中,类型说明用来说明指针变量可以指向的目标变量类型,目标变量类型既可以是Fortran中提供的内部数据类型。如INTEGER、REAL等,也可以是用户自行定义的派生数据类型。不管适合哪种数据类型,目标变量都必须在程序的声明阶段被赋予
3、TARGET属性。属性关键字POINTER说明被定义的变量具有指针属性,能够用于指向类型说明中规定类型的变量。指针变量名列表由若干个指针变量名组成,变量名之间用逗号“,”进行分隔。指针变量名的命名规则同普通变量是一致的,但不允许与其他的变量同名。13.1.2 定义指针范例下面是一些合法的指针变量定义范例:INTEGER, POINTER : Alp, A 2p(:)REAL, POINTER : Mp, Np(:, :)COMPLEX, POINTER : CpCHARACTER, POINTER : SpTYPE(Personal_Information) : Tp在上面的范例中,第一行语句
4、声明了一个整型指针变量A1p和一个整型指针数组A2p;第二行则声明了一个实型指针变量Mp和一个二维的实型指针数组Np;第三行则声明了一个复型指针数组Cp;第四行则声明了一个字符型指针变量Sp;最后一行则声明了一个自定义数据类型的指针变量Tp。在实际编程中,也可以将类型说明与指针说明分成两行来书写,即先说明变量的类型,然后再定义变量的指针属性。例如下面的语句同样定义了两个整型的指针变量A1p和A2p:INTEGER : A1p, A2p(:)POINTER : Alp, A2p 13.2 指针的基本应用 在Fortran语言中,指针能够与之进行联合的变量既可以是其他非指针变量,也可以是通过动态内
5、存分配得到的一块内存。13.2.1 指针的基本用途 下面通过一个具体的实例来说明指针变量最基本的用途,即与其他非指针变量进行联合从而操纵相应存储空间中的数据。 (详细内容请参照本书)13.2.2 指针与变量的关系接下来的程序代码演示了Fortran中指针与变量之间的相互关系。在前两次操作中,将变量X的值分别设置为10和3,打印的结果显示指针P所保存的值也随着变量X的值而变化。在最后一次操作中,则直接将指针P的值设置为35,这相当于将P指向内存地址的内容设置为35,结果显示与指针联合的变量X的值也变成了35。在Compaq Visual Fortran中,可以使用LOC内部函数来获得变量的内存地
6、址,因此在程序的最后,通过LOC语句来查看两个变量在内存中的地址,结果发现指针P与变量X共享了同一块内存单元。实际上,在Fortran语言中,指针一旦与某个变量建立起了联合,则该指针就会与这个变量共享同一块存储空间,而不会像其他高级程序设计语言那样单独开辟一块存储单元来保存变量的地址。这就好像药品,除了有化学上的名称外,还可以有商品名称。13.2.3 动态分配和释放指针空间指针除了指向非指针变量外,还可以通过动态内存分配来得到一块内存。来看下面的例子:TEST1303.F90 ! 动态分配指针空间PROGRAM TEST1303 IMPLICIT NONE! 变量定义 REAL, POINTE
7、R : A INTEGER : Err! 为指针分配存储空间 ALLOCATE(A, STAT=Err) IF(0 /= Err) THEN PRINT *, 分配指针的存储空间失败!STOP ENDIF A = 3.1415926 PRINT *, PEND PROGRAM TEST130313.2.4 指针状态的查询和更改在使用一个指针之前,可以通过ASSOCIATED内部函数来查询指针当前的状态。语句的使用形式如下:ASSOCIATED(pointer, target)该内部函数用于检查指针是否设置了指向,返回值为逻辑型变量。如果函数只含有一个指针参数,则会检查该指针是否已经建立联合;如
8、果函数含有两个参数,则会检查第一个指针参数是否与第二个目标参数联合。除了查询函数,Fortran语言中还提供NULL空置函数来确保指针指向一个不能使用的内存地址,从而保证ASSOCIATED能够正确判断出指针还没有与任何目标建立联合。语句的使用形式如下:NULL()13.2.5 指针分享存储空间 在使用指针时,除了建立一对一的联合之外,还可以同时用多个指针指向同一个变量。下面就来看一个实例:13.3 指针与数组 指针除了能够声明成单一变量的形式外,还可以声明成数组的形式,称为指针数组。声明成数组的指针可以有两种基本的使用方法: 将指针指向一个数组、数组片断或数组元素; 配置一定的内存空间来使用
9、。13.3.1 指针指向数组利用指针来指向一个数组,能动态地分配数组空间,给编程带来极大的方便。由于FORTRAN语言在使用数组时必须在可执行语句之前进行定义,而一般定义数组的方法是在声明阶段就指定数组的维界,确定数组存储空间的大小。但在编写实际的程序时,通常很难事先确定所需数组的大小。如果定义的数组空间较小很可能无法满足运行中的需要,一种解决办法就是将数组定义得足够大,但这样做通常会浪费计算机的存储空间。通过动态定义,可以根据当时实际所需存储空间的大小来申请,既避免了存储空间的浪费,又能够满足程序运行的需要。1定义指针数组2指针数组的秩13.3.2 动态分配指针数组指针数组除了上面提到的这种
10、用法外,还可以通过ALLOCATE语句来动态分配内存空间进行使用。也就是说,指针数组也可以当作可变大小的数组来使用。在数组一章中也曾经提到过可分配数组的概念和用途,指针数组与可分配数组非常相似。那么这两者之间有什么区别呢?可分配数组在程序中有自己的生存周期,它仅存在于声明它的过程中,过程执行完毕后会由系统自动收回它所占用的临时存储空间。但是指针数组在声明它的过程执行完毕后,不会由系统自动回收它所占用的存储空间,程序员必须自行通过DEALLOCATE语句来释放掉指针数组所占用的存储空间。如果程序员没有在过程中使用DEALLOCATE语句来释放存储空间,则指针数组占用的存储空间只能等待整个程序执行
11、完毕后由系统来回收。13.4 指针与过程 指针也可以作为参数传递进过程中(包括函数子程序和子例行子程序),并可以作为函数的结果返回主调程序。在使用指针作为过程的相关参数时,需要注意以下一些问题: 当使用指针作为参数传递进过程时,在主调过程中必须对被调函数进行显式的接口说明,即必须编写INTERFACE接口; 指针参数在声明时不需要使用INTENT属性进行说明; 如果函数的返回值为指针,也需要对该函数进行显式的接口说明,即必须编写INTERFACE接口。13.4.1 指针与过程的示例 下面来看一段实际的实例代码。 (详细内容请参照本书) 在上面的程序中,分别演示了函数子程序与子例行子程序中使用指
12、针数组的方式。函数GetMax会将输入的指针数组中的最小值找出来,函数的虚参类型及返回值都是指针,因此需要在主调过程中显式的说明函数的调用接口。如果不在主调过程中说明函数的调用接口,则在程序的运行过程中很可能发生参数传递不正确的情况。同样的道理也适用于子例行子程序,在主调程序也需要显式声明调用接口。 13.4.2 在指针与过程中使用模块 在实际使用中,通常会直接编写模块来避免在主调程序中重复书写涉及到指针过程的调用接口。在主调过程中直接引用模块就相当于声明了指针过程的调用接口。下面的代码将TEST1310改写成了模块的形式,需要注意的是,如果模块与主程序编写在同一个源代码文件中时,则模块的代码
13、必须出现在引用它的过程之前,否则会出现错误;如果模块与调用过程不在同一个源代码文件中,则不存在这种问题,编译程序会自动确定模块目标文件的位置。13.5 指针的简单应用 在一些实际应用中,使用指针能够非常快速的交换数据。对于一些需要移动大量存储单元的应用来说,指针是非常理想的工具。例如一些派生数据类型的应用,使用指针可以避免移动大量的存储单元,从而优化程序的执行速度。13.6 指针与链表概述指针除了可以间接的使用变量,以及作为指针数组来加以使用外,另一个重要的用途就是使数据在计算机中以链接方式进行存储。例如“串行结构”、“树形结构”等。链式存储在计算中最重要的一项应用就是动态使用内存。在编写程序
14、中时常会遇到一些预先无法确切知道存储空间大小的情况,以前的处理方法通常就是声明一个很大的存储空间来保存数据。这种做法在程序运行时,其中大量的存储空间是被浪费的。链式存储能够较好的解决这一问题,它可以根据需要向计算机“申请”合适的内存来使用。链式存储中最简单的应用就是链表。下面介绍关于链表的一些基本知识。13.7 单向链表在计算机的早期应用中,节约内存是程序设计中一个非常重要的方面。因为当时的计算机内部存储空间有限,这就要求程序必须短小精悍才能在狭窄的舞台施展拳脚。尽管目前计算机的硬件发展相当快,目前主流配置个人计算机的内存容量一般也在2GB左右,但是应用程序对内存的需求也是与日俱增。而且目前的
15、操作系统大多支持多任务操作,即计算机能够同时运行多个程序。操作系统能够运行的程序个数,通常取决于计算机内存的大小。单个程序占用的内存越少,能够同时执行的程序就越多(当然程序的运行效率不会高)。因此,节约内存的使用仍然是有必要的。在数据的存储方面,顺序存储和链式存储是两种最基本的存储结构。在顺序存储中,每个存储结点只保存与存储元素本身相关的信息,元素之间的逻辑关系只需通过数组下标的值就可以确定下来。例如在一个顺序表中,如果某一个元素存储在对应的数组中的下标值为N,则在逻辑上比它靠前的一个元素在对应的数组中的下标是N一1,比它靠后的一个元素就是数组中下标为N+1的元素。13.7.1 单向链表的基本
16、概念先来看一个简单的例子,这个例子用于建立单向链表的概念,实际使用中不会采用下面的方式来建立和使用链表。TEST1313.F90 ! 单向链表的基本概念PROGRAM TEST1313 IMPLICIT NONE! 链表节点定义 TYPE Link INTEGER : Number TYPE(Link), POINTER : Next END TYPE TYPE(Link), TARGET : P1, P2, P3! 节点赋值 P1%Number = 1 P1%Next = P2 P2%Number = 3 P2%Next = P3 P3%Number = 5 P3%Next =NULL()!
17、 打印节点值 PRINT *, P1%Number PRINT *, P1%Next%Number PRINT *, P1%Next%Next%NumberEND PROGRAM TEST1313 13.7.2 节点的定义 在链表中,节点是用于存放数据的基本单位,它通常是一个派生数据类型。在单向链表中,节点包含两个数据部分:一个部分称为数据域,用于存储要保存的数据;另一个部分称为指针域,用来保存链表中下一个节点的内存地址。可以用下面的一般形式来表示单向链表中的节点: TYPE Link 数据域 TYPE(Link), POINTER : Next END TYPE13.7.3 节点的引用 链表
18、建立好之后,就可以通过节点的引用来访问节点数据域中的内容。在实例程序中,使用了一种很原始的方法来访问各个节点: PRINT *, P1%Number PRINT *, P1%Next%Number PRINT *, P1%Next%Next%Number 由于程序中已经进行了P1%Next=P2的设置,程序中如果引用P1%Next就相当于引用节点P2。因此,打印语句中的P1%Next%Number就相当于使用P2%Number一样。 同样的道理,对P1%Next%Next%Number的引用就相当于对P2%Next%Number或是P3%Number的引用。13.7.4 链表的建立 上面的代码
19、中,链表的建立方式并不“聪明”。程序中的链表只有三个节点,编写起程序来似乎并不麻烦,如果需要建立的链表有成百上千个节点呢?实际上,现实编程中不会用前面的方式来建立链表。前面示范程序的链表建立方式中,每一个节点都有自己的名字,引用时完全可以直接通过名字来进行,体现不出链表在使用上的优势。真正建立链表时,通常只需要定义链表中第一个节点的名字就可以了,在建立过程中通过指针就可以建立起整个链表。 13.8 双向链表和环状链表除了单向链表,在日常编程中还会经常用到双向链表和环状链表。单向链表在使用中,只能按照链表建立时的顺序,一个节点接一个节点的读下去,无法逆向进行访问。双向链表和环状链表就不会存在这种
20、问题。双向链表和环状链表的节点定义上完全相同,区别就在于首末两个节点的定义上。双向链表和环状链表的节点比单向链表的节点多出一个指针域,用于指出前一个节点在内存中的地址。这两种形式的链表节点可以用下面的形式来表示:TYPE Link TYPE(Link), POINTER : Previous 数据域 TYPE(Link), POINTER : NextEND TYPE13.8.1 双向链表的建立在建立链表的其余节点时,需要清楚的知道上一条数据和下一条数据的位置。上面的程序在创建链表的循环中,利用了如下的语句来建立当前节点与上一节点和下一节点的逻辑关系:DO J = 2, N ALLOCATE(
21、P%Next, STAT=Err) IF(0 /= Err) THEN PRINT *, 内存分配失败! P%Next = NULL() EXIT ENDIF P%Next%Previous = P P = P%Next WRITE(P%Name, (第, I1, 个节点) J P%Number = JENDDO13.8.2 环状链表的建立 单向链表和双向链表都是有头有尾的,环状链表则是一种无头无尾的特殊链表。来看下面的环状链表实例,这是前面双向链表的一个改进程序。链表使用的节点同前一个程序中定义的节点完全相同。下面给出环状链表的程序源代码。 (详细内容请参照本书)13.9 链表的基本操作 在
22、前面的小节中介绍了几种链表的基本概念及其建立方式和简单的引用方式,除此之外,链表的使用还包括其他一些基本的操作。这些操作包括链表节点的插入、删除、查找、更新和遍历等,本节将介绍链表建立后在链表中插入、删除节点等基本操作的具体实现方法。13.9.1 插入及删除操作 使用链表的一个突出优点就是可以根据需要随时往链表中插入或者删除节点。如果类似的操作使用数组来完成,就会显得相当的麻烦:如果插入新的元素后数组中元素的数量超过了原始定义的数组大小,则必须使用动态内存分配才能实现类似操作;删除操作尽管不会造成数组元素超出数组的存储范围,但是会造成存储空间的浪费。此外,使用数组来完成节点的插入在效率上较低,例如要在具有N个数组元素数组的第M个元素的位置处插入一个数据,则需要移动N-M个数组元素的位置。N-M的值越大,效率就越
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025版养老院入住后法律援助与权益维护合同3篇
- 2025版上市公司员工薪酬协议书范本3篇
- 2025年食品行业电商平台广告监测服务合同3篇
- 2025版健身房运营管理权及设备租赁合同4篇
- 2025年高科技企业实习生保密协议与研发成果归属合同3篇
- 2025年度煤矿井巷工程劳务派遣与人员培训承包合同范本4篇
- 2025年度个人借款合同电子化管理规范4篇
- 2025版淋浴房防水保温材料供应与施工合同4篇
- 2025版事故责任赔偿协议范本:交通事故赔偿15篇
- 2025年高端皮鞋定制加工合同范本3篇
- 无人化农场项目可行性研究报告
- 《如何存款最合算》课件
- 社区团支部工作计划
- 拖欠工程款上访信范文
- 《wifi协议文库》课件
- 中华人民共和国职业分类大典是(专业职业分类明细)
- 2025年新高考语文复习 文言文速读技巧 考情分析及备考策略
- 2024年海口市选调生考试(行政职业能力测验)综合能力测试题及答案1套
- 一年级下册数学口算题卡打印
- 2024年中科院心理咨询师新教材各单元考试题库大全-下(多选题部分)
- 真人cs基于信号发射的激光武器设计
评论
0/150
提交评论