6

I recently came across the question of how to compare two pointers in Fortran. In C one can compare two pointers with (pA == pB) (with pA and pB being pointers) as they are just addresses. But in fortran pointers are more than pure memory addresses. The code if(pa.ne.pb) (with pa and pb being pointers of the same type) gives me an error

Operands of comparison operator '.ne.' at (1) are TYPE(sometype)/TYPE(sometype)

where sometype is the type the pointer is pointing to.

Is there a way to compare whether two pointers point to the same target? Or do I have to create a .ne.-operator for the type being pointed to?

PVitt
  • 11,500
  • 5
  • 51
  • 85
  • 1
    [This isn't an answer, but] for the example `if(pa.ne.pb)` this isn't a comparison of the pointers, but of the targets of the pointers. Creating a naive defined operator for this type won't help solve the problem of seeing whether the targets are the same variable (rather than having the same value). – francescalus Oct 23 '15 at 13:13
  • 3
    You're probably looking for the intrinsic function `associated`, see your favourite reference material for an explanation. – High Performance Mark Oct 23 '15 at 13:40

2 Answers2

15

As High Performance Mark comments the associated intrinsic can partly do what you want:

if (.not.ASSOCIATED(pa, pb)) ...

In many cases, using associated with two pointer arguments will tell you whether the two targets "occupy the same storage units". In some senses this is the case when the pointers are pointing to the same target.

integer, target :: a
integer, pointer :: pa, pb
pa=>a; pb=>a

print*, ASSOCIATED(pa, pb)

Alas, things aren't so simple.

Another restriction for scalar targets is that they are not zero-sized storage. Take the following case

type t
end type t

type(t), target :: a
type(t), pointer :: pa, pb
pa=>a; pb=>a

print*, ASSOCIATED(pa, pb)

The output of this, if a variable of type t has zero-sized storage, must be .FALSE., even though they are certainly the same target. The storage size of an object of type t is an implementation detail.

The same holds for zero-sized arrays, although it is clear that the result here is .FALSE.:

integer, target :: a(0)
integer, pointer :: pa(:), pb(:)
pa=>a; pb=>a

print*, ASSOCIATED(pa, pb)

If you have such pathological cases of the first kind that you care about there may be a possibility to consider using C addresses and Fortran 2003 C interoperability.

The c_associated function compares the C addresses determined by c_loc. Continuing the above code with type(t) targets,

print*, C_ASSOCIATED(C_LOC(pa), C_LOC(pb))

may be more forgiving. Again, whether it works depends on the implementation.

This approach with C addresses will not help in the case of zero-length strings or zero-sized arrays: using c_loc is prohibited in these cases.

To conclude, it is generally the case that ASSOCIATED(pa, pb) returns .TRUE. if and only if pa and pb point to the same target, but there are exceptions in both directions.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • Thanks for the detailed answer. I'm a little ashamed that I didn't know about `associated` being capable of doing this. But I anyway wouldn't have known about the details you provided. – PVitt Oct 24 '15 at 11:54
4

The associated() function takes a second optional pointer argument. You can then test if both pointers are associated with the same target:

if (associated(pA, pB)