Fortran函数一次性获取指针的关联状态和大小
Fortran function to get association status and size of a pointer in one go
我正在编写一个 Fortran (2003) 整数函数来检查指向任意元素数组的指针的关联状态和大小,使用 class(*)
。如果没有关联,则为return-1,否则为数组元素个数。假定指针被定义为指向null()
。
目标是避免两个后续的 if
语句。 (我知道在 C 中可以将 2 个检查合并为一个语句。)
代码在 gfortran (6.1.0) 和 Intel 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_field
时的任何指针实际参数,在本例中为 tp
,必须是与目标关联的指针。
在第一次引用时,tp
没有关联指针。
至于如何满足你的要求,"non-optional"部分是一个很大的提示。在 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
但是,解决限制的 "non-optional" 部分是解决问题的唯一有用方法。尝试将伪参数改为指针是没有帮助的:对于多态伪指针参数,实际参数也必须是多态的(对于无限多态伪参数,实际参数也必须是无限多态的)。
我正在编写一个 Fortran (2003) 整数函数来检查指向任意元素数组的指针的关联状态和大小,使用 class(*)
。如果没有关联,则为return-1,否则为数组元素个数。假定指针被定义为指向null()
。
目标是避免两个后续的 if
语句。 (我知道在 C 中可以将 2 个检查合并为一个语句。)
代码在 gfortran (6.1.0) 和 Intel 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_field
时的任何指针实际参数,在本例中为 tp
,必须是与目标关联的指针。
在第一次引用时,tp
没有关联指针。
至于如何满足你的要求,"non-optional"部分是一个很大的提示。在 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
但是,解决限制的 "non-optional" 部分是解决问题的唯一有用方法。尝试将伪参数改为指针是没有帮助的:对于多态伪指针参数,实际参数也必须是多态的(对于无限多态伪参数,实际参数也必须是无限多态的)。