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

Function Fortran函数:指针作为实际参数,目标作为形式参数,function,pointers,fortran,Function,Pointers,Fortran,我正试图破译一个fortran代码。它将指向函数的指针作为实际参数传递,而形式参数则是目标。它在主程序中定义并分配globalDATA类型的指针,然后调用传递该指针的函数: module dataGLOBAL type globalDATA type (gl_1) , pointer :: gl1 type (gd_2) , pointer :: gd2 type (gdt_ok) , pointer :: gdtok ... ...

我正试图破译一个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
这样做的意义是什么?为什么主程序中的指针和目标结构的单个组件都必须分配? 谢谢
A.

对于本身包含指针的用户定义类型的指针变量,您必须分配(即创建存储)整个变量和组件指针。在启用总体变量时,不会自动分配组件。有人做了一个设计选择,在主程序中分配总体变量,在子例程中分配组件。也许他们认为分配整个变量很简单,但分配所有组件变得复杂,他们想把它放到一个子例程中。

一些事情可能会起作用

  • 如果将指针作为实际参数提供给一个过程,而对应的伪参数不具有pointer属性(此处为这种情况),则与伪参数关联的对象就是实际参数指针的目标。因此,在本例中,正在传递的对象是
    GD
    (在主程序中)指向的对象-由allocate语句分配的对象。(当实际参数和伪参数都有指针参数时,指针本身被“传递”-您可以更改指针指向的对象,并且该更改会反映回调用范围。)

  • 由于函数中的
    GD
    伪参数具有target属性,因此函数中的指针可以指向伪参数。您不会显示此类指针的任何声明,但它们可能在省略的代码中。如果没有任何东西指向
    GD
    伪参数(包括INIT函数可能调用的任何过程),则目标属性是多余的,但除了抑制某些优化之外,它是无害的

  • 具有指针属性的东西(根据语言规则自动)也具有目标属性-因此主程序中的
    GD
    具有目标属性。主程序和函数中的
    GD
    都具有target属性这一事实可能是相关的,因为

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

  • globalDATA
    类型的组件本身就是指针。因此,主程序中的
    GD
    是指向某个对象的指针(该对象由主程序中的单个ALLOCATE语句分配),该对象本身包含指向其他对象的指针(由函数中的许多ALLOCATE语句分配的其他内容)。您有两个级别的指针,因此有两个级别的ALLOCATE

  • Fortran 2003之前(或带有“可分配TR”的Fortran 95)派生类型中不能有可分配的组件,也不能有可分配的伪参数——当动态分配的需要与以前的限制冲突时,即使只将指针用作值,也必须使用指针。我强烈怀疑您的代码可以追溯到这个时代(对可分配TR的支持大约在十年前开始普及)。在非常“现代”的Fortran中,指针(应该?)仅在您可能希望变量指向其他对象(其他对象包括“无对象”)时使用


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

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

type(globalDATA), intent(inout), target :: GD
更清楚地说,伪参数的target属性只确保您可以通过指针赋值在子例程中指向该参数

只要您只操作派生类型的字段,而不是整个派生类型(例如,通过分配或取消分配),那么无论您是通过传递指针调用
INIT
例程,还是通过派生类型本身调用
INIT,都不会有什么不同


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

好的,谢谢,我知道您已经分配整体变量和组件指针。但我在fortran 95手册或web上找不到任何关于指针是实际参数而目标是形式的可能性的提及。这合法吗?如果形式也被声明为指针而不是目标,会有什么不同?感谢poiNT4,当伪参数和实际参数都是目标时:指针关联保证在t结束后继续存在