根据对象,我正在努力理解返回可分配数组的函数背后的逻辑。我喜欢这种结构,因为与子例程相比它更清晰,而且 fortran 中的纯函数是编写干净的函数式编程代码的绝佳方式。
假设我必须编写一个简单的函数,返回一个具有任意边界的索引数组,例如在这个程序中:
program test_allocatable_functionReturn
implicit none
integer, allocatable :: fun(:),sub(:),noa(:)
integer, parameter :: low = -4
integer, parameter :: hi = 3
call testsub(sub,low,hi)
fun = testfun(low,hi)
noa = testfun_noalloc(low,hi)
print '(4(a,i3),a)', 'testsub: lbound=',lbound(sub),'(expected = ',low,'), ubound=',ubound(sub),'(expected = ',hi,')'
print '(4(a,i3),a)', 'testfun: lbound=',lbound(fun),'(expected = ',low,'), ubound=',ubound(fun),'(expected = ',hi,')'
print '(4(a,i3),a)', 'no alloc: lbound=',lbound(noa),'(expected = ',low,'), ubound=',ubound(noa),'(expected = ',hi,')'
contains
pure function testfun_noalloc(low,hi) result(array)
integer, intent(in) :: low,hi
integer :: array(low:hi)
integer :: i
forall(i=low:hi) array(i) = i
end function testfun_noalloc
pure function testfun(low,hi) result(array)
integer, allocatable :: array(:)
integer, intent(in) :: low,hi
integer :: i
allocate(array(low:hi))
forall(i=low:hi) array(i) = i
end function testfun
pure subroutine testsub(array,low,hi)
integer, intent(out), allocatable :: array(:)
integer, intent(in) :: low,hi
integer :: i
allocate(array(low:hi))
forall(i=low:hi) array(i) = i
end subroutine testsub
end program
我通过三种方式实现了它:
- 返回可分配数组的函数 (
testfun
) - 子程序 (
testsub
) - 返回静态数组的函数 (
testfun_noalloc
)
该子例程对返回数组进行操作,并正确分配它。(-4:3)
在示例中,应返回一个大小合适的数组。在任一实现中,该函数都返回一个(1:hi-low+1)
-sized 数组:
testsub: lbound= -4(expected = -4), ubound= 3(expected = 3)
testfun: lbound= 1(expected = -4), ubound= 8(expected = 3)
no alloc: lbound= 1(expected = -4), ubound= 8(expected = 3)
为什么会这样?我得到这样一个事实,即在将函数返回值分配给我的 LHS 数组时,fortran 可能会重新分配数组,但即便如此,为什么它没有分配正确的边界?我知道在将静态数组传递给具有 f2003 风格的 lhs 重新分配的可分配对象时可能会发生这种情况,但是以可分配数组作为输入,我希望保留边界信息。我在这里错过了什么吗?顺便说一句,这个例子是用 gfortran 9.2.0 编译的。
谢谢,费德里科