Class Fortran函数,可一次性获取指针的关联状态和大小

Class Fortran函数,可一次性获取指针的关联状态和大小,class,fortran,polymorphism,intel-fortran,Class,Fortran,Polymorphism,Intel Fortran,我正在编写一个Fortran(2003)整数函数,使用class(*)检查指向任意元素数组的指针的关联状态和大小。如果不关联,则返回-1,否则返回数组的元素数。假定指针是指向null()定义的 目标是避免两个后续的if语句。(我知道在C中,这两个检查可以组合成一个语句。) 该代码在gfortran(6.1.0)和英特尔ifort(17.0.4)下编译和运行,但只有gfortran提供了所需的结果 完整的代码包括一个测试例程和一个名为“size_field”的函数,如下所示: program tp

我正在编写一个Fortran(2003)整数函数,使用
class(*)
检查指向任意元素数组的指针的关联状态和大小。如果不关联,则返回-1,否则返回数组的元素数。假定指针是指向
null()
定义的

目标是避免两个后续的
if
语句。(我知道在C中,这两个检查可以组合成一个语句。)

该代码在gfortran(6.1.0)和英特尔ifort(17.0.4)下编译和运行,但只有gfortran提供了所需的结果

完整的代码包括一个测试例程和一个名为“size_field”的函数,如下所示:

program tpa  
implicit none  
real,pointer :: tp(:)=>null()  

                      write (6,*) size_field(tp)  
allocate   (tp(53));  write (6,*) size_field(tp)  
deallocate (tp);      write (6,*) size_field(tp)  
tp=>null();           write (6,*) size_field(tp)  
allocate   (tp(0));   write (6,*) size_field(tp)  
deallocate (tp);      write (6,*) size_field(tp)  

contains

   function size_field(ff)  
   integer :: size_field  
   class(*),target  :: ff(:)  
   class(*),pointer :: field(:)  
   field => ff  
   size_field=-1 ! shall indicate not associated  
   if (associated(field)) size_field=size(field)  
   end function  

end program 
使用gfortran(默认编译器选项)编译,输出如预期:

-1
53
-1
-1
 0  
-1  
使用ifort(默认编译器选项)编译,输出为:

 0  
53  
53  
53  
 0  
 0  
为什么ifort没有给出我想要的结果?

如果我将
class(*)
替换为
real
,ifort编译的程序也会显示正确的结果。

您的程序不是有效的Fortran。当被要求编译这个程序时,编译器可以给出它喜欢的任何结果

伪参数
ff

   class(*), target :: ff(:)  
是一个非指针、非可选的伪参数,因此(Fortran 2018 15.5.2.3 p1)引用函数
size_字段
(在本例中为
tp
)时,任何指针实际参数都必须是与目标关联的指针

在第一个引用中,
tp
没有指针关联

至于如何满足您的需求,“非可选”部分是一个很大的提示。在Fortran 2008+下,可以将伪参数设置为可选参数,然后在引用函数时,实际参数不需要与指针关联。如果实际参数未与指针关联,则不存在伪参数:

function size_field(ff)
  integer :: size_field
  class(*), target, optional :: ff(:)

  if (PRESENT(ff)) then
    size_field = SIZE(ff)
  else
    size_field = -1
  end if

end function

然而,解决限制的“非可选”部分是解决问题的唯一有效方法。尝试将伪参数改为指针是没有帮助的:对于多态伪指针参数,实际参数也必须是多态的(对于无限制多态伪参数,实际参数也必须是无限制多态的)。

感谢您的快速回答。然而,你的建议也不起作用。我想补充一点,使用调试选项编译会更改结果。gfortran-C-g-fcheck=全壁tpa.f90给出了与上述相同的结果。ifort-C-g-warn all-debug-all tpa.f90会导致分段错误。似乎我必须重新编写子程序,或者使用两个if语句来接受经过测试的方法;我必须检查需要哪些编译器版本。对不起,我在尝试你的新版本时出错了。我现在可以确认,它在我的平台上使用gfortran(6.1.0)和ifort(17.0.4)时确实可以正常工作。谢谢你的帮助。我不知道在Fortran 2008中使用了可选关键字。是的,这是Fortran 2008编译器的行为(参见Fortran 2008 12.5.2.12,类似于Fortran 2018)。(虽然更准确地说,它是不存在的伪参数。)Fortran 2008确实引入了这一特性:“空指针可用于表示不存在的不可分配的非指针可选参数。”(JTC 1/SC 22/WG5/N1791)。gfortran和英特尔fortran编译器的文档中也介绍了这一点。