Fortran函数:指针作为实际参数,目标作为形式

时间:2013-01-07 01:43:22

标签: function pointers fortran

我正在尝试破译fortran代码。它将指向函数的指针作为实际参数传递,而形式参数则是目标。它在主程序中定义并分配类型为globalDATA的指针,然后调用传递该指针的函数:

module dataGLOBAL
 type globalDATA
   type (gl_1)      , pointer :: gl1
   type (gd_2)      , pointer :: gd2
   type (gdt_ok)    , pointer :: gdtok
   ...
   ...
 end type globalDATA
end module dataGLOBAL


Program main
....
....
use dataGLOBAL   
...
type(globalDATA),pointer :: GD

allocate(GD)
returnvalue = INIT(GD)
....
....
end

该函数显示:

integer function INIT(GD) result(returnvalue)
....
....
use dataGLOBAL

type(globalDATA)  , target   :: GD

allocate (GD%gl1)
allocate (GD%gd2)
allocate (GD%gdtok)
....
....
end function INIT

这样做是什么意思?为什么必须分配主程序中的指针和目标结构的单个组件? 谢谢 甲

3 个答案:

答案 0 :(得分:9)

有些事情可能会发挥作用......

  • 当你提供一个指针作为一个过程的实际参数,其中相应的伪参数没有POINTER属性(这里的情况),与伪参数关联的东西是实际的目标参数指针。所以在这种情况下,传递的东西是GD(在主程序中)指向的对象 - 由allocate语句分配的东西。 (当实际和伪参数都有POINTER参数时,则POINTER本身被“传递” - 您可以更改POINTER指向的内容,并且该更改将反映在调用范围内。)

  • 因为函数内的GD伪参数具有target属性,所以函数内的指针可以指向伪参数。您没有显示此类指针的任何声明,但可能它们是在省略的代码中。如果没有任何指向GD伪参数(包括可能被INIT函数调用的任何过程内),那么TARGET属性是多余的,但除了禁止某些优化之外无害

  • 具有指针属性的东西(由语言规则自动生成)具有TARGET属性 - 因此主程序中的GD具有TARGET属性。主程序和函数BOTH中GD具有目标属性的事实可能是相关的,因为......

  • 当伪参数具有TARGET属性并且实际参数传递的东西具有TARGET属性时,与过程内的伪参数关联的指针也是“通常”(存在异常/处理器依赖性)与相应的实际参数相关联的coindexed事物/非连续数组/向量下标部分对我来说太复杂了。如果指针不是局部变量(可能是模块中声明的指针),则此关联在过程结束后仍然存在。也许这与删除的代码相关。 (或者,如果实际参数没有TARGET属性,则在过程结束时,与伪参数关联的任何指针都将变为未定义。)

  • globalDATA类型的组件本身就是指针。因此,主程序中的GD是指向某个东西的指针(由主程序中的单个ALLOCATE语句分配的东西),它本身包含指向其他东西的指针(那些其他东西由多个ALLOCATE语句分配)功能)。你有两个指针级别,因此有两个级别的ALLOCATE。

  • 在Fortran 2003(或带有“可分配TR”的Fortran 95)之前,你不能在派生类型中拥有ALLOCATABLE组件,并且你不能拥有ALLOCATABLE伪参数 - 当动态分配的需要与这些相冲突时以前的限制你不得不使用指针,即使你只是使用指针作为值。我强烈怀疑你的代码可以追溯到这个时代(支持可分配的TR在大约十年前就已经普及)。在非常“现代”的Fortran指针中(应该?)只在你可能想要指向其他东西的变量时才使用(其他东西包括“没有东西”)。

答案 1 :(得分:2)

如果指针变量是用户定义的类型,它本身包含指针,则必须分配(即创建存储)整个变量和组件指针。当整个变量为时,不会自动分配组件。有人做了一个设计选择,在主程序中分配整个变量,在子程序中分配组件。也许他们认为分配整个变量很简单,但是分配所有组件变得越来越复杂,并希望将其转移到子程序中。

答案 2 :(得分:0)

因为没有为伪参数指定指针属性,所以从主代码(而不是指向它的指针)传递整个派生类型GD。在子程序方面,你可以明确地写

integer function INIT(GD) result(returnvalue)
...
use dataGLOBAL

type(globalDATA), intent(inout), target :: GD

使其更清晰。伪参数的target属性只能确保您可以通过指针赋值指向 in 子例程中的参数。

只要您只是操纵派生类型的字段,而不是整个派生类型(例如通过分配或取消分配它),它是否应该有所不同,无论您是否调用INIT例程通过传递指针或派生类型本身。

正如其他答案中已经指出的那样,程序的目的似乎是将派生类型及其组件的分配彼此分开。这种策略的一个可能的优点是可以将指针和静态分配的派生类型传递给INIT例程。