如何将可分配数组传递给Fortran中的子例程

下面的代码是返回一个分段错误,因为我试图通过的可分配数组没有被正确识别(大小返回1,当它应该是3)。 在这个页面(http://www.eng-tips.com/viewthread.cfm?qid=170599)一个类似的例子似乎表明它应该在F95中正常工作; 我的代码文件有一个.F90扩展名,但我试图将其更改为F95,我正在使用gfortran进行编译。

我的猜测是,问题应该以我将可分配数组传递给子例程的方式进行; 我究竟做错了什么?

!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! PROGRAM test !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! IMPLICIT NONE DOUBLE PRECISION,ALLOCATABLE :: Array(:,:) INTEGER :: iii,jjj ALLOCATE(Array(3,3)) DO iii=1,3 DO jjj=1,3 Array(iii,jjj)=iii+jjj PRINT*,Array(iii,jjj) ENDDO ENDDO CALL Subtest(Array) END PROGRAM !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! SUBROUTINE Subtest(Array) DOUBLE PRECISION,ALLOCATABLE,INTENT(IN) :: Array(:,:) INTEGER :: iii,jjj PRINT*,SIZE(Array,1),SIZE(Array,2) DO iii=1,SIZE(Array,1) DO jjj=1,SIZE(Array,2) PRINT*,Array(iii,jjj) ENDDO ENDDO END SUBROUTINE !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%! 

如果一个过程有一个可分配的伪参数,那么在任何调用范围内都需要显式接口。

(有很多事情需要一个明确的接口,可分配的虚拟只是一个。)

您可以通过在子程序中为您的子程序添加一个接口块来提供这个明确的接口。 另一种更好的select是将子程序放在模块中,然后在主程序中使用该模块 – 然后自动创build显式接口。 在eng-tips网站上有一个这样的例子,你提供了一个链接 – 看xwb的post。

请注意,如果您要执行与其分配状态有关的事情 – 查询其状态,重新分配它,取消分配等,那么只有具有allocatable属性的伪参数才有意义。

还请注意,你的可分配伪参数array是用intent(in)声明的,这意味着它的分配状态将是相关实际参数的分配状态(在过程中它可能不会被改变)。 传递给子例程的实际参数可能是未分配的,因此即使使用明确的接口,也是非法的。 编译器不会知道这一点,在这种情况下,像size这样的查询的行为是不确定的。

因此,您首先必须在引用其内容之前检查分配的array的分配状态allocated(array) 。 我会进一步build议在lboundubound的整个数组上实现循环,因为一般来说你不能确定array的边界:

 subroutine subtest(array) double precision, allocatable, intent(in) :: array(:,:) integer :: iii, jjj if(allocated(array)) then print*, size(array, 1), size(array, 2) do iii = lbound(array, 1), ubound(array, 1) do jjj = lbound(array, 2), ubound(array, 2) print*, array(iii,jjj) enddo enddo endif end subroutine 

这是一个简单的例子,使用可分配的虚拟参数与模块。

 module arrayMod real,dimension(:,:),allocatable :: theArray end module arrayMod program test use arrayMod implicit none interface subroutine arraySub end subroutine arraySub end interface write(*,*) allocated(theArray) call arraySub write(*,*) allocated(theArray) end program test subroutine arraySub use arrayMod write(*,*) 'Inside arraySub()' allocate(theArray(3,2)) end subroutine arraySub