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?
We can compare pointers if they are pointing to the same array. Relational pointers can be used to compare two pointers. Pointers can't be multiplied or divided.
In Go language, you are allowed to compare two pointers with each other. Two pointers values are only equal when they point to the same value in the memory or if they are nil. You can perform a comparison on pointers with the help of == and !=
The subtraction of two pointers gives the increments between the two pointers. For Example: Two integer pointers say ptr1(address:1000) and ptr2(address:1016) are subtracted. The difference between address is 16 bytes.
Comparison operators can be used to compare two pointers. Only equality operators (operator== and operator!=) can be used to compare the following pointer pairs: two pointers-to-members. a null pointer constant with a pointer or a pointer-to-member.
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With