Pointers Fortran:如何强制可选数组伪参数为“未定义地址”?

Pointers Fortran:如何强制可选数组伪参数为“未定义地址”?,pointers,fortran,undefined,Pointers,Fortran,Undefined,Fortran:如何强制可选数组伪参数的未定义地址 我有一个很长的故事,请不要问为什么这需要在一个调用语句中保留一个实际的可选参数给一个接受可选数组伪参数的s/r,但仍然将它们视为.NOT。在某些情况下出现。比如说 Integer, Target :: n Integer, Pointer :: m ! Real(DP), Target :: ArrA(n) Real(DP), Pointer :: ArrB(:) ! Logical :: lSomething ! m

Fortran:如何强制可选数组伪参数的未定义地址

我有一个很长的故事,请不要问为什么这需要在一个调用语句中保留一个实际的可选参数给一个接受可选数组伪参数的s/r,但仍然将它们视为.NOT。在某些情况下出现。比如说

Integer, Target :: n
Integer, Pointer    :: m
!
Real(DP), Target    :: ArrA(n)
Real(DP), Pointer   :: ArrB(:)
!
Logical     :: lSomething
!
m => n
!
If( lSomething ) Then
   n = 5
Else
   Nullify(m)
End If
!
Allocate(ArrB(n))
!
ArrB => ArrA
!
If( lSomething ) Then
   ArrA(1:n) = (/"... n values ..."/)
Else
   Nullify(ArrB)
End If
!
Call sr(ArrA, ArrB,n, m)    ! the idea is for ArrB, and m to "pretend" to be .Not. Present if they are Null.
!

....

Subroutine sr(A,BX,n, mX)   ! where the suffix "X" is my notation for Optional Vars
!
Integer, Intent(In)         :: n
Real(DP), Intent(In)        :: A(n)
!
Integer, Intent(In), Optional   :: mX
Real(DP, Intent(In), Optional   :: BX(:)
!
If( Present(mX) ) Then      ! this works correctly with Nullify'd pointer, when mX = "undefined pointer/array"
   !
   ! do something
End If
!
If( Present(BX) ) Then      ! this works INcorrectly with Nullify'd pointer, when BX = "undefined pointer/array", but works correctly if BX has the value "undefined address"
   !
   ! do something else
End If
.....
目前,我使用的策略是创建一个指向调用序列中可选项的指针,并传递该指针

要明确的是,当实际的Args指针指向一个合适的值或数组时,这一切都会一直起作用。当试图通过在其位置发送空指针来假装省略了可选参数时,问题就来了

如果指针为Nullify'd,则s/r将收到一个Arg,其值应为未定义的指针/数组

伪参数不是指针,它们是普通变量

因此,我们的想法是让未定义的虚拟Arg显示为不存在。例如,在行(如果存在)中,未定义的var应注册为.Not。现在

此策略非常适用于标量参数。即:

If( Present(mX) ) Then
   ! do something
End If
然后,如果m作为null'd指针传递,则mX具有值undefined pointer/array,并且if PresentmX语句在mX is.NOT中正确运行。现在,即“做某事”未到达

不幸的是,对于可选阵列,这将失败。例如,在上述完全相同的策略中,尽管必须分配一个与BX秩一致的指针,并将其置零,var BX的值为undefined Pointer/array。。。但是现在的BX调查报告是真的。。也就是说,即使虚拟数组变量是未定义的指针/数组,它仍然存在。然后,即使它为空,也会到达“做其他事情”对话框。。。不应该的时候

我的猜测是,分配实际Arg的行为,即使它为null,也会在内存中创建一个nothing数组,就目前而言,它仍然是一个数组,例如,SizeBX小于1

相反,如果实际省略了可选的Arg ArrB,例如:

Call sr(ArrA, n = n, mX = m)
然后它的伪参数BX的值为undefined address。这与通过Nullify的未定义指针/数组不同

换言之,显然,要使当前查询正确使用数组Args,值必须是未定义的地址,而不是未定义的指针/数组


有人知道如何强制数组伪参数的值为undefined address而不是undefined pointer/array吗?或者当前的查询是否与标量和数组一致?或者???你的问题很难理解。我猜你是指这样的事情。您肯定不必分配指针或可分配数组来在可选参数中传递它

program p
  integer, pointer :: a(:) => null()

  call sub()

  call sub(a)

  allocate(a(10))
  a = 0

  call sub(a)

  deallocate(a)

contains
  subroutine sub (ptr)
    integer, pointer, optional :: ptr(:)
    if (present(ptr)) then
      if (associated(ptr)) then
        print *, "present associated"
      else
        print *,"not associated"
      end if
    else
      print *, "not present"
    end if
  end subroutine
end
您可以查询参数是否存在,以及它是否关联

输出:

> ./a.out
 not present
 not associated
 present associated
请注意,未定义的指针与未关联的空指针不同。您不能对任何内容使用未定义的指针,甚至不能查询其关联状态

您可以将其用于可分配项,而不是指针


你绝对不能有一个地址未定义的普通伪参数,这是语言所禁止的。

要让它工作,而不让伪参数像VladimirF那样成为指针,你需要购买或编写Fortran 2008编译器

Fortran 2008将未分配的可分配变量和分离的指针变量添加到与普通的非可分配、非指针可选参数关联时被视为不存在的内容列表中。实际参数的秩必须与伪参数的秩匹配,但此功能可用于标量和数组

如果您的面前没有Fortran 2008编译器,那么您就不走运了。未实现此功能的编译器在面对未分配或未分离的实际参数时可能会传递无意义的信息,对于标量和数组,它们的行为可能会有所不同,因为它们通常在内部描述符方面处理方式不同


在您的示例代码中,您的语句只会泄漏内存。

为此干杯,但在本例中,这不是解决方案。我试图避免解释的时间过长,但我确实规定dummy Arg不是指针。我的设置涉及调用数百个s/r,没有切实可行的方法来重写所有s/r并更改其虚拟类型。至于不能有未定义的地址,是的,你肯定可以。这就是眼前的全部问题。当调用中实际省略了数组Arg时,虚拟地址是未定义的地址,然后Present可以正常工作。试着带着手表走过去。。。事实就是这样。而且,如果我重新编写这些s/r,保留dum会更好地服务于我的情况
我的参数是非指针,而是在If PresentBX测试中使用类似If SizeBX<1的内容。在这种情况下,未定义的地址只意味着作为参数描述一部分的底层计算机指针指向调试器无法读取的地方。特定机器指针的值是否意味着参数不存在取决于特定编译器的内部结构-对于某些实现,参数存在的指示与为参数传递的地址无关。为此干杯。不幸的是,弗拉基米尔夫的建议并不是一个开始,原因是他解释了对他的建议的回应。我将了解F2008,但我不认为我的代码只是泄漏内存。。。虽然为了简洁起见,这里省略了,但在实际代码中,调用这些s/r的s/r中的所有指针都是null'd/DeAlloc'd。我显然不知道实际代码是做什么的,但上面的示例代码肯定会泄漏。问题中的语句虽然必须分配一个指针,使其与BX的秩一致,并且将其置零是没有意义的-秩是Fortran中变量的编译时属性,但要解释为什么您所说的与我的情况没有多大关系,需要花费很长的时间。实际参数和伪参数之间需要秩一致性,无论是否为指针。我确信我上面所说的是正确的,因为它是有效的,并且在更复杂和更一般的环境中工作,没有泄漏等。事实上,如果我尝试以不同的方式来做,它不会编译。让我们继续关注这个问题,这里的问题是如何在标量和数组中保持一致的行为。。。不过还是要谢谢你,当我感到困惑时,我会告诉你:-