纯函数中的指针 [英] Pointers in pure functions

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

问题描述

为了在 Fortran 中遍历链表,我使用指向当前元素的指针,该指针在循环中移动到下一个元素.尝试在对所述链表进行操作的 pure 函数中应用它会导致错误.

In order to traverse a linked list in Fortran, I use a pointer to the current element that is moved to the next one inside a loop. Trying to apply this inside a pure function that operates on said linked list results in an error.

例子:

module list
  implicit none

  ! Node
  type n_list
    integer               :: val
    type(n_list),pointer  :: next => NULL()
  end type

  ! Linked list
  type t_list
    type(n_list),pointer  :: head
  end type

contains

  pure function in_list( list, val ) result(res)
    implicit none
    class(t_list),intent(in)  :: list
    integer,intent(in)        :: val
    logical                   :: res
    type(n_list),pointer      :: cur

    res = .true.
    ! Traverse the list
    cur => list%head
    do while ( associated(cur) )
      if ( cur%val == val ) return 
      cur => cur%next
    enddo

    ! Not found
    res = .false.
  end function
end module

结果

    cur => list%head
         1
Error: Bad target in pointer assignment in PURE procedure at (1)

我知道错误/警告背后的基本原理,并且很难确保在使用指针时不会更改函数的参数(Fortran 2008,第 12.7 章纯过程",尤其是 C1283).但是,在这种情况下,list 永远不会改变.

I am aware of the rationale behind the error/warning, and that it is difficult to ensure that the arguments of the function are not changed when using pointers (Fortran 2008, ch. 12.7 "Pure procedures", esp. C1283). In this case, though, list is never changed.

是否可以告诉编译器(ifortgfortran)intent(in) 没有违反?

Is it possible to tell the compiler (ifort and gfortran) that intent(in) is not violated?

推荐答案

好的,我找到了使用 transfer 内在函数的解决方案.主要思想是克隆列表结构(没有数据,我检查了),并使用指向第一个节点(未更改)的指针作为起始值.是的,这是一个漏洞,但 ifortgfortran 都接受了这一点而不会发出警告.

OK, I found a solution using the transfer intrinsic. The main idea is to clone the list struct (without the data, I checked), and use the pointer to the first node (unchanged) as a start value. Yeah, it is a loop-hole, but both ifort and gfortran accept this without warnings.

module list_mod
  implicit none

  ! Node
  type n_list
    integer               :: val
    type(n_list),pointer  :: next => NULL()
  end type

  ! Linked list
  type t_list
    type(n_list),pointer  :: head
  end type

contains

  pure function getHead(list) result(res)
    implicit none
    class(t_list),intent(in)  :: list
    type(n_list),pointer      :: res
    type(t_list),pointer      :: listPtr

    ! Create a copy of pointer to the list struct
    allocate( listPtr )
    listPtr = transfer( list, listPtr )

    ! Set the pointer
    res => listPtr%head

    ! Free memory
    deallocate( listPtr )
  end function

  pure function in_list( list, val ) result(res)
    implicit none
    class(t_list),intent(in)  :: list
    integer,intent(in)        :: val
    logical                   :: res
    type(n_list),pointer      :: cur

    res = .true.

    ! Traverse the list
    cur => getHead(list)
    do while ( associated(cur) )
      if ( cur%val == val ) return
      cur => cur%next
    enddo

    ! Not found
    res = .false.
  end function

end module

program test
  use list_mod
  implicit none
  integer,parameter     :: MAXELEM = 10000000
  integer               :: i
  type(t_list)          :: list
  type(n_list),pointer  :: cur

  ! Fill list
  list%head => NULL()
  allocate( list%head )
  list%head%val = 1

  cur => list%head
  do i=2,MAXELEM
    allocate( cur%next )
    cur%next%val = i
    cur => cur%next
  enddo !i

  print *,'is MAXELEM/2 in list? ', in_list( list, MAXELEM/2 )
  print *,'is MAXELEM+1 in list? ', in_list( list, MAXELEM+1 )
end program

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

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