我希望从子例程中检测到,与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令我惊讶的是,它适用于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
$ 有什么想法吗?谢谢!
发布于 2022-11-30 16:43:45
碎片
iPtr => null()
print *, "passing iPtr => null()"
call pointer_detect(iPtr)违反Fortran标准并使您的程序无效(Fortran 2008,25.5.2.3):
除对内部查询函数的引用外,对应于非可选非指针虚拟参数的指针实际参数应是与目标相关联的指针。
非内在过程的虚拟参数既不是可选的,也不是指针.
避免这个问题的责任完全是程序员和the compiler has no duty为您检测这个坏代码。
但是,如果被要求,编译器很可能能够检测到这样的错误(通常在运行时):
At line 19 of file brokenpointer.f90
Fortran runtime error: Pointer actual argument 'iptr' is not associated是使用gfortran和-fcheck=pointer编译选项时的输出,或者
forrtl: severe (408): fort: (7): Attempt to use pointer IPTR when it is not associated with a target和艾弗特的-check pointers。
程序员无法在过程本身中可靠地进行类似的检查,因为Fortran编译器没有义务尊重以这种方式破坏规则的程序员。
看看这个过程在这里的努力,例如:
iPtr => iVal
if (associated(iPtr)) theniVal不是指针,因此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如果与不相关的指针实际参数相关联,则非指针、不可分配的可选虚拟参数将被视为不存在。
但是,请注意,如果iPtr具有未定义的关联状态,这将不会对您有所帮助。Nothing will.
发布于 2022-11-30 11:40:48
如果指针为null,则call pointer_detect(iPtr)不符合标准。例程pointer_detect()的名称很差,因为它不能检测到关于原始指针的任何内容,而原始指针根本没有传递:虚拟参数不是指针,因此在调用时编译器将传递iPtr目标的地址,而不是iPtr本身。但是如果iPtr是空的,那么它就没有目标:行为没有定义。
一个未定义的行为是,嗯,未定义的。或者说不可预测。它可能崩溃,或输出不可预测的值,等等.在编译时无法真正检测到这种违反标准的行为,编译器也不需要这样做。但是,gfortran可能有编译选项,可以在运行时进行检测(与任何其他运行时检查一样,性能会受到影响)。
https://stackoverflow.com/questions/74625857
复制相似问题