指向纯函数 [英] Pointers in pure functions
问题描述
为了遍历Fortran中的链表,我使用一个指向当前元素的指针,该指针移动到循环中的下一个元素。试图在 示例: 结果 我知道错误/警告背后的基本原理,并且很难确保函数的参数在使用指针时不会发生变化(Fortran 2008,第12.7节纯粹的过程,尤其是 C1283)。但在这种情况下, 是否可以告诉编译器( 好的,我找到了一个使用 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 Example: Results in 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, Is it possible to tell the compiler ( OK, I found a solution using the
这篇关于指向纯函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!> pure 函数中应用这个函数,该函数在所述链表上运行会导致错误。
模块列表
隐式无
!节点
类型n_list
整数:: val
类型(n_list),pointer :: next => NULL()
结束类型
!链接列表
类型t_list
类型(n_list),指针::头部
结束类型
包含
纯函数in_list(list, val)result(res)
implicit none
class(t_list),intent(in):: list
整数,intent(in):: val
logical :: res
类型(n_list),指针:: cur
res = .true。
!遍历列表
cur =>如果(cur%val == val)返回
cur =>列表%head
while(associated(cur))
do cur%next
enddo
!未找到
res = .false。
结束功能
结束模块
cur => (1)
$ b中的PURE过程中的指针赋值中的目标不正确$ b list
永远不会改变。
ifort
和 gfortran
) intent(in)
没有违反?
传输
内部函数的解决方案。主要思想是克隆列表结构(没有数据,我检查过),并使用指向第一个节点的指针(不变)作为起始值。是的,这是一个循环漏洞,但是 ifort
和 gfortran
在没有警告的情况下接受它。
模块list_mod
隐式无
!节点
类型n_list
整数:: val
类型(n_list),pointer :: next => NULL()
结束类型
!链接列表
类型t_list
类型(n_list),指针::头部
结束类型
包含
纯函数getHead(list)结果(res)
隐式无
类(t_list),意图(in)::列表
类型(n_list),指针:: res
类型(t_list),指针: :listPtr
!创建指向列表的指针的副本struct
allocate(listPtr)
listPtr = transfer(list,listPtr)
!设置指针
res => listPtr%head
!空闲内存
deallocate(listPtr)
结束函数
纯函数in_list(list,val)结果(res)
隐式无
class(t_list) ,intent(in):: list
integer,intent(in):: val
logical :: res
type(n_list),pointer :: cur
res = .true。
!遍历列表
cur => getHead(list)
while(associated(cur))
if(cur%val == val)return
cur => cur%next
enddo
!未找到
res = .false。
结束函数
结束模块
程序测试
使用list_mod
隐式无
整数,参数:: MAXELEM = 10000000
integer :: i
type(t_list):: list
type(n_list),pointer :: cur
!填写清单
清单%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 *,'是列表中的MAXELEM / 2吗? ',in_list(list,MAXELEM / 2)
print *,'是列表中的MAXELEM + 1? ',in_list(list,MAXELEM + 1)
end program
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)
list
is never changed. ifort
and gfortran
) that intent(in)
is not violated?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