Rou*_*oux 3 standards fortran pointers
我想从子例程内部检测到传递的虚拟参数intent(in)实际上是空指针:
program testPTR
implicit none
integer, target :: ii
integer, pointer :: iPtr
iPtr => ii
iPtr = 2
print *, "passing ii"
call pointer_detect(ii)
print *, "passing iPtr"
call pointer_detect(iPtr)
iPtr => null()
print *, "passing iPtr => null()"
call pointer_detect(iPtr)
contains
subroutine pointer_detect(iVal)
implicit none
integer, intent(in), target :: iVal
integer, pointer :: iPtr
character(len = *), parameter :: sub_name = 'pointer_detect'
iPtr => iVal
if (associated(iPtr)) then
print *, "Pointer associated. Val=", iVal, ", iPtr = ", iPtr
else
print *, "Pointer not associated. Val=", iVal, ", iPtr = ", iPtr
endif
end subroutine pointer_detect
end program
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是它适用于 gfortran-9 和 gfortran-12。不过我有几个问题:
$ gfortan test.f90
$ ./a.out && echo ok
passing ii
Pointer associated. Val= 2 , iPtr = 2
passing iPtr
Pointer associated. Val= 2 , iPtr = 2
passing iPtr => null()
Pointer not associated. Val= 0 , iPtr = 0
ok
$
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?谢谢你!
片段
iPtr => null()
print *, "passing iPtr => null()"
call pointer_detect(iPtr)
Run Code Online (Sandbox Code Playgroud)
违反了 Fortran 标准并使您的程序无效(Fortran 2008, 25.5.2.3):
除了对内部查询函数的引用之外,与非可选非指针虚拟参数相对应的指针实际参数应是与目标关联的指针。
非内在过程的虚拟参数既不是可选的,也不是指针。
避免这个问题的责任完全在于程序员,编译器没有责任为您检测这个损坏的代码。
但是,如果被要求,编译器很可能能够检测到此类错误(通常在运行时):
At line 19 of file brokenpointer.f90
Fortran runtime error: Pointer actual argument 'iptr' is not associated
Run Code Online (Sandbox Code Playgroud)
是使用 gfortran 和编译选项时的输出-fcheck=pointer,或者
forrtl: severe (408): fort: (7): Attempt to use pointer IPTR when it is not associated with a target
Run Code Online (Sandbox Code Playgroud)
与 ifort 的-check pointers.
程序员无法在过程本身内可靠地执行类似的检查,因为 Fortran 编译器没有义务尊重以这种方式违反规则的程序员。
看看这里的过程的努力,例如:
iPtr => iVal
if (associated(iPtr)) then
Run Code Online (Sandbox Code Playgroud)
iVal不是指针,因此iPtr在该指针赋值中与该变量相关联。编译器可以假设您没有违反 Fortran 规则,因此iptr是关联的并且测试条件始终为真。没有有效的 Fortran 程序可以使该测试条件解析为 false。
然而,并非所有希望都破灭了。我引用的标准中的文本说的是“非指针”以外的东西:它说的是“非可选”。如果iVal是可选使用PRESENT():
subroutine pointer_detect(iVal)
implicit none
integer, intent(in), optional :: iVal
character(len = *), parameter :: sub_name = 'pointer_detect'
if (present(iVal)) then
print *, "Actual argument pointer was associated. Val=", iVal
else
print *, "Actual argument pointer was not associated."
endif
end subroutine pointer_detect
Run Code Online (Sandbox Code Playgroud)
如果与不关联的指针实际参数关联,则非指针、不可分配、可选虚拟参数将被视为不存在。
iPtr但请注意,如果是未定义的关联状态,这对您没有帮助。什么都不会。