问题描述
为了在 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.
是否可以告诉编译器(ifort
和 gfortran
)intent(in)
没有违反?
Is it possible to tell the compiler (ifort
and gfortran
) that intent(in)
is not violated?
推荐答案
好的,我找到了使用 transfer
内在函数的解决方案.主要思想是克隆列表结构(没有数据,我检查了),并使用指向第一个节点(未更改)的指针作为起始值.是的,这是一个漏洞,但 ifort
和 gfortran
都接受了这一点而不会发出警告.
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
这篇关于纯函数中的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!