Fortran中的指针数组 [英] Array of pointers in Fortran

查看:0
本文介绍了Fortran中的指针数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为热力学计算编写了一个大型Fortran程序将近10年了,当我开始时,我对新的Fortran标准还很陌生(我熟悉F77,太老了,学不了其他东西)。我发现新的类型构造非常好,并且经常使用它们,但我没有意识到一些限制,比如它不允许创建指针数组,这是我后来发现的。

现在我正在更正我的一些旧代码,我很惊讶地在记录声明中发现:type GTP_PHASE_ADD

声明:type(TpfunExpression),Dimension(:),Points::explink

其中explink用于指向包含数学表达式的另一个结构。这没有产生任何编译错误(我通常使用gfortran,但我也用英特尔fortran编译了这个程序)。当我看到这段旧代码(大约写于10年前)时,我以为其中缺少一个可分配的代码,但添加该代码会导致编译错误。

我制作了一个最小的完整程序来模拟它的使用方式:

MODULE test1
  implicit none
  
  TYPE tpfun_expression
     integer nc
     double precision, allocatable, dimension(:) :: coeffs
     integer, allocatable, dimension(:) :: powers
  END type tpfun_expression

  TYPE gtp_phase_add
!**************************************************************************
! My question is if it is correct Fortran to have an array of pointers here
     TYPE(tpfun_expression), dimension(:), pointer :: explink
!**************************************************************************
     TYPE(gtp_phase_add), pointer :: nextadd
  END TYPE gtp_phase_add

contains

  subroutine create_tpfun(n,coeffs,powers,exp)
    integer n,i,powers(*)
    double precision coeffs(*)
    type(tpfun_expression), pointer :: exp
    allocate(exp%coeffs(n))
    allocate(exp%powers(n))
    exp%nc=n
    do i=1,n
       exp%coeffs(i)=coeffs(i)
       exp%powers(i)=powers(i)
    enddo
    return
  end subroutine create_tpfun

  subroutine create_addrec(typ,this)
    integer typ,n,m
    TYPE(tpfun_expression), target :: exp1
    TYPE(tpfun_expression), pointer :: exp2
    TYPE(gtp_phase_add), pointer :: this
    integer ipow(4)
    double precision coeffs(4)
!
!**************************************************************************
! here I allocate a pointer array
    allocate(this%explink(typ))
!**************************************************************************
    if(typ.eq.1) then
       do m=1,4
          ipow(m)=m-1
          coeffs(m)=2.0D0*m
       enddo
       exp2=>this%explink(1)
       call create_tpfun(4,coeffs,ipow,exp2)
    else
       do m=1,4
          ipow(m)=m-1
          coeffs(m)=3.0D0
       enddo
       exp2=>this%explink(1)
       call create_tpfun(4,coeffs,ipow,exp2)
       do m=1,3
          ipow(m)=1-m
          coeffs(m)=5.0D0
       enddo
       exp2=>this%explink(2)
       call create_tpfun(3,coeffs,ipow,exp2)
    endif
    return
  end subroutine create_addrec

end MODULE test1

program main
  use test1
  integer n,m,j,k,q
  TYPE(gtp_phase_add), target :: addrec
  TYPE(gtp_phase_add), pointer :: next,first
  TYPE(tpfun_expression) :: exp
  
  first=>addrec
  next=>addrec
  write(*,*)'Creating addrec 1'
  call create_addrec(1,next)
  allocate(next%nextadd)
  write(*,*)'Creating addrec 2'
  next=>next%nextadd
  call create_addrec(2,next)
! just a check that the functions are correct
  write(*,*)'Listing functions in all addrecs'
  next=>first
  q=0
  do while(associated(next))
     q=q+1
     write(*,*)'Addition record ',q
     n=size(next%explink)
     do m=1,n
        k=next%explink(m)%nc
        write(*,10)(next%explink(m)%coeffs(j),next%explink(m)%powers(j),j=1,k)
     enddo
10   format(10(F6.3,1x,i3))
     next=>next%nextadd
  enddo
end program main

这正如我预期的那样工作,我只是惊讶于我允许声明一个指针数组,所以我想知道这是否是正确的Fortran。‘ 如果我不能理解如何更优雅地编辑此内容,我深表歉意。

推荐答案

可以,您可以拥有一个具有POINTER属性的数组。考虑一下简单的代码

program foo
  integer, target :: i(10)
  integer, pointer :: j(:)
  i = [(n,n=1,10)]
  j => i
  print '(10(I3))', j
end program foo

使用gfortran编译时,没有任何警告/错误(对于正确的程序应该没有),并且输出为 1 2 3 4 5 6 7 8 9 10。上面的一个稍微复杂一点的版本是

program foo
  integer, pointer :: j(:)
  allocate(j(10))
  j = [(n,n=1,10)]
  print '(10(I3))', j
end program foo

allocate语句将分配一个具有10个元素的匿名目标(因为没有更好的名称)。j指向匿名目标。这里与第一个程序的不同之处在于j = [(n,n=1,10]是内在赋值,而在前者中j => i是指针赋值。

PS:如果不需要pointer,最好使用allocatable

这篇关于Fortran中的指针数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆