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

时间:2012-10-24 22:23:56

标签: arrays fortran fortran90 gfortran

以下代码返回分段错误,因为我尝试传递的可分配数组未被正确识别(大小返回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
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!

3 个答案:

答案 0 :(得分:30)

如果过程具有可分配的伪参数,则在任何调用范围中都需要显式接口。

(有很多东西需要显式接口,可分配的虚拟只有一个。)

您可以通过在主程序中放置子程序的接口块来自己提供该显式接口。另一个远远更好的选择是将子程序放在一个模块中,然后在主程序中使用该模块 - 然后自动创建显式接口。您在eng-tips网站上提供了一个链接的示例 - 请参阅xwb的帖子。

请注意,如果您要执行与其分配状态相关的操作,则只有具有allocatable属性的伪参数才有意义 - 查询其状态,重新分配,解除分配等等。

答案 1 :(得分:6)

请注意,您的可分配伪参数array是使用intent(in)声明的,这意味着它的分配状态将是相关实际参数的分配状态(并且在过程中可能不会更改)。传递给子例程的实际参数可能是未分配的,因此即使使用显式接口也无法引用。编译器不会知道这一点,在这种情况下,size之类的查询行为是未定义的。

因此,首先必须在引用其内容之前检查arrayallocated(array)的分配状态。我还建议使用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

答案 2 :(得分:1)

This is a simple example that uses allocatable dummy arguments with a module.

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