开篇:润墨网以专业的文秘视角,为您筛选了一篇通过与Fortran 的混合编译在C 中实现动态数组范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!
摘要:动态数组在数据处理时有着独特的优势,Fortran语言数组功能强大并支持动态数组,而C语言不支持动态数组。利用Fortran与C/C++的混合编译思想,通过调用fortran90例程的方法,在C中实现动态数组并给出了程序代码。
关键词:动态数组;Fortran;C/C++;混合编译;调用约定
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2013)18-4192-03
数组是处理大量数据时的有力助手。在不能够事先确定数组大小的情况下,为避免数据溢出或越界,就要足够大的数组。这种方法使用过度,会迟滞内存操作。故此,理想的数组能够动态确定大小,即程序运行中先向系统申请一个大数组,不使用时再将其内存空间释放掉。而动态数组很好地满足了这一要求。但C语言不支持动态数组,不能动态定义数组元素的数量。如何解决这一矛盾将是本文的着力点。
1 Fortran中的动态数组
Fortran90数组功能强大,执行程序时能够动态分配数组存储空间和实际大小,不使用时再将其内存释放还给系统;支持直接操作数组段、数组整体;支持逐个操作数组元素;支持面向数组操作的函数和构造块[1]。Fortran 90中运用动态数组需要三个步骤:
1)声明动态数组。明确数组的维数,不规定维的上、下界和大小(即延迟形状数组)。如:REAL,DIMENSION(:),ALLOCATABLE::X。
2)给动态数组分配内存。如:ALLOCATE(X(N))。
3)将分配的内存释放掉。如:DEALLOCATE(X)。
2 Fortran与C/C++的混合编译
在32位Windows系统下,同时安装Compaq Visual Fortran 6.x和Microsoft Visual C++ 6.0,则两者共享一个可视化开发环境(Microsoft Visual Studio 6.0)[1]。Fortran与C/C++任一种语言都可以作为主程序,调用另一种语言编写的例程。但两者在目标例程命名、堆栈管理以及参数传递方面的行为模式不完全一致,要协调其调用约定。
Fortran使用的调用约定有缺省约定(Default)、STDCALL约定和C约定。在Visual Fortran 6.x的编译器下,作用于例程参数和整个外部例程的属性不同,会影响堆栈管理、例程命名、参数传递。
2.1 堆栈管理
Fortran与C/C++间的例程调用是通过堆栈进行的。在缺省约定和STDCALL约定下,堆栈由被调用例程(Colleen)控制。在C约定下,堆栈由调用程序(Caller)控制,所以例程参数驻留在堆栈什么位置、占用多少字节等信息都是调用程序获知,该约定下传递参数的数量是可以变化的,是可选参数[2]。
2.2 例程命名
在编译生成的目标文件(.OBJ)中,标示符诸如全局变量、外部例程、模块等,在整个程序作用域内是独一无二的,共享于各个程序单元[3]。C对字母的大小写敏感,C++增加了特定的修饰,而Fortran忽略字母大小写,使得目标标示符在编译后发生变化。而命名约定,就是保持目标标示符在编译时一致性的命名规则。为保证链接成功,就要协调命名约定。
C++增加的修饰受特定系统影响,如将其去掉,就是在函数中添加C链接选项(extern “C”),则C++与C的命名约定相同。
协调Fortran与C/C++的例程命名分大写、小写和混合三种情况:
1)大写。Fortran是缺省约定,其目标外部例程名统一被转换为大写,那么在C/C++中须采用_stdcall约定,并用大写命名外部函数。
2)小写。Fortran是C约定或STDCALL约定,其目标外部例程名统一被转换为小写,那么在C/C++中须采用缺省约定_cdecl或_stdcall约定,并用小写命名外部函数。
3)大小写混合。C/C++的外部函数名是大小写混合形式,在Fortran中若要保持一致的形式,必须采用ALIAS属性来限定产生的目标例程名。
2.3参数传递
1)参数传递方式
Fortran参数传递方式取决于调用约定[4]。Default状态下,Fortran为引用传递;C或STDCALL约定状态下,数组参数为引用传递;单个参数为值传递。在调用约定之外,为忽略掉调用约定对参数传递的影响,可以规定参数拥有VALUE和REFERENCE传递属性[5]。在混合编程中,应通过VALUE和REFERENCE属性明确规定参数的传递方式,而不是依赖于调用约定。
C/C++参数传递方式不受调用约定影响。数组参数为引用传递;单个参数为值传递。单个参数可转换为引用方式传递,C中可选指针参数;C++中可选指针参数或引用参数。
2)数据类型的对应
要使Fortran和C/C++的混合编程获得成功,不仅要求对其调用约定、命名约定等进行协调,还要求保持数据类型相互一致。事实上,实型和整型是数值计算过程中经常运用到的,并且在两种语言中其数据类型有着很好的一致性,其对应关系如表1。
3 C中动态数组的实现实例
下面给出一个利用Fortran与C/C++的混合编译在C中实现动态数组的实例。该实例包含以一个外部例程,其功能是利用动态数组实现学生成绩及学生人数的输出。
具体实现过程如下:打开安装好的开发环境,Microsoft Visual C++ 6.0或Compaq Visual Fortran 6.x中的Developer Studio界面,点击new text file快捷按钮,保存为(.f90)文件,在其中编写Fortran外部例程。
代码如下:
SUBROUTINE PrintMarks(Students)
IMPLICIT NONE
!DEC$ ATTRIBUTES STDCALL,ALIAS:'_PrintMarks@4'::PrintMarks
!DEC$ ATTRIBUTES VALUE::Students
INTEGER(4) :: Students
REAL,ALLOCATABLE::Marks(:)
INTEGER K
WRITE(*,'(A)',ADVANCE='NO') 'How many student:'
READ*,Students
ALLOCATE(Marks(Students))
DO K=1, Students
PRINT*,'输入第',k,'个学生的成绩:'
READ*,Marks(K)
END DO
PRINT*,Marks
DEALLOCATE(Marks)
print*,Students
END SUBROUTINE
同理,再建立一个(.c)文件编写主程序,在C中调用Fortran例程。
主程序代码如下:
#include
void main()
{ void _stdcall PrintMarks(int Students);
int Students=0;
PrintMarks(Students); }
编写好程序代码后,以(.c)文件建立链接并生成活动的工作空间,将Fortran外部例程的文件添加到工作空间中,混合编译即可获得成功,得到正确的运行结果:通过C程序中调用Fortran例程在C中实现动态数组。
4 结论
通过C程序调用Fortran例程的混合编译方法,实现了C语言的动态数组功能,一定程度上弥补了C不支持动态数组的缺憾。此外,Fortran90其他的优势数组功能可否通过调用的方式增强C数组功能的不足,或许是可行的研究方向。
参考文献:
[1] 周振红.Fortran 90/95 高级程序设计[M].郑州:黄河水利出版社,2005.
[2] 任慧,周振红,张成才.Fortran与C/C++的混合编译[J].计算机工程与设计,2007(9):4096-4098.
[3] 毕苏萍,周振红,贺晓慧.Fortran90借用C++函数模板[J].郑州大学学报:工学版,2013(3):64-66.
[4] 周振红,王国宾,毕苏萍.Fortran与VB传递单一字符串的几种方式[J].郑州大学学报:工学版,2011(1):116-120.
[5] 周涛,郭占元,郭向荣.FORTRAN与C#混合编程在土木工程计算中的应用[J].山东交通学院学报,2009(3):80-85.