在Fortran语言中,为具有TARGET属性的伪参数的过程提供一个没有TARGET属性的参数应该会导致代码无效。但是,当使用gfortran(5.1.0)或ifort(14.0.0)编译以下代码时,不会检测到错误,并且程序的行为类似于参数实际具有TARGET属性。当我说它是无效代码或者这是编译器缺陷时,我错了吗?
program pointerization
implicit none
integer, dimension(3) :: A
integer, dimension(:), pointer :: ptr_A
A = [1, 2, 3]
call pointerize(A, ptr_A)
print*, "A=", ptr_A
contains
subroutine pointerize(tab, ptr_tab)
integer, dimension(:), intent(in), target :: tab
integer, dimension(:), pointer :: ptr_tab
ptr_tab => tab
end subroutine
end program
答案 0 :(得分:5)
您的代码无效是正确的。但是,由于你说的原因,它不是。
在一个过程中,即使相关的实际参数不具有目标属性,伪参数也是合法的。基本上,只要指向的生命周期不超过过程的生命周期,我们就可以在程序中指定实体。
在这个问题的情况下,即使相关的实际参数tab
没有,也允许伪参数A
具有目标属性。甚至程序中的指针赋值语句ptr_tab => tab
也是合法的。
然而,重要的是,在程序之外,实际参数没有目标属性,我们不能通过指针影响该实体。 Fortran标准确保这不会以下列方式发生(Fortran 2008 C.9.4,另见12.5.2.4;类似Fortran 2018中存在):
如果非指针伪参数具有TARGET属性且相应的实际参数不具有,则任何与伪参数关联的指针,因此与实际参数关联的指针 程序的执行,在程序执行完成时变为未定义。
也就是说,就问题而言,完成pointerize
ptr_A
后不再具有已定义的关联状态。
有兴趣的是,使用nagfor编译示例代码会导致运行时诊断
Runtime Error: aaa.f90, line 9: Reference to dangling pointer PTR_A
Target was RETURNed from procedure POINTERIZATION:POINTERIZE
Program terminated by fatal error
Abort (core dumped)
但同样,仅仅因为指针关联未定义,这并不意味着您无法获得预期的结果。这样的检查对于编译器来说是一件好事,但它并不是要求它失败。