REAL, POINTER :: var
They are conceptually a descriptor listing the attributes
of the objects (targets) that the pointer may point to,
and the address, if any, of a target.
They have no associated storage until it is allocated
or otherwise associated (by pointer assignment, see below):
ALLOCATE (var)
and they are dereferenced automatically, so no special symbol required.
In
var = var + 2.3
the value of the target of var is used and modified.
Pointers cannot be transferred via I/O. The statement
WRITE *, var
writes the value of the target of var and not
the pointer descriptor itself.
A pointer can point to other pointers, and hence to their targets, or to a static object that has the TARGET attribute:
REAL, POINTER :: object
REAL, TARGET :: target_obj
var => object ! pointer assignment
var => target_obj
but they are strongly typed:
INTEGER, POINTER :: int_var
var => int_var ! illegal - types must match
and, similarly, for arrays the ranks as well as the type must agree.
A pointer can be a component of a derived type:
TYPE entry ! type for sparse matrix
REAL value
INTEGER index
TYPE(entry), POINTER :: next ! note recursion
END TYPE entry
and we can define the beginning of a linked chain of such entries:
TYPE(entry), POINTER :: chain
After suitable allocations and definitions, the first two entries could
be addressed as
chain%value chain%next%value
chain%index chain%next%index
chain%next chain%next%next
but we would normally define additional
pointers to point at, for instance, the
first and current entries in the list.
DEALLOCATE (p, q) ! for returning storage
NULLIFY (p, q) ! for setting to 'null'
The intrinsic function ASSOCIATED can test the association status of a defined pointer:
IF (ASSOCIATED(pointer)) THEN
or between a defined pointer and a defined
target (which may, itself, be a pointer):
IF (ASSOCIATED(pointer, target)) THEN
REAL, TARGET :: b(10,10), c(10,10), r(10), s(10, z(10)
REAL, POINTER :: a(:,:), x(:), y(:)
INTEGER mult
:
DO mult = 1, 2
IF (mult == 1) THEN
y => r ! no data movement
a => c
x => z
ELSE
y => s ! no data movement
a => b
x => r
END IF
y = MATMUL(a, x) ! common calculation
END DO
For objects of derived type we have to distinguish between pointer
and normal assignment. In
TYPE(entry), POINTER :: first, current
:
first => current
the assignment causes first to point at current, whereas
first = current
causes current to overwrite first and is equivalent to
first%value = current%value
first%index = current%index
first%next => current%next
REAL, POINTER :: a
:
ALLOCATE (a(80, 80)
:
CALL sub(a)
:
SUBROUTINE sub(c)
REAL c(:, :)
USE data_handler
REAL x(100)
REAL, POINTER :: y(:)
:
y => compact(x)
where the module data_handler contains
FUNCTION compact(x)
REAL, POINTER :: compact(:)
REAL x(:)
! A procedure to remove duplicates from the array x
INTEGER n
: ! Find the number of distinct values, n
ALLOCATE(compact(n))
: ! Copy the distinct values into compact
END FUNCTION compact
The result can be used in an expression (but must be associated
with a defined target).
TYPE(entry) :: rows(n)
then
rows%next ! illegal
would be such an object, but with an irregular storage pattern. For
this reason they are not allowed. However, we can achieve the same
effect by defining a derived data type with a pointer as its sole
component:
TYPE row
REAL, POINTER :: r(:)
END TYPE
and then defining arrays of this data type:
TYPE(row) :: s(n), t(n)
where the storage for the rows can be allocated by, for instance,
DO i = 1, n
ALLOCATE (t(i)%r(1:i)) ! Allocate row i of length i
END DO
The array assignment
s = t
is then equivalent to the pointer assignments
s(i)%r => t(i)%r
for all components.
REAL, TARGET :: table(100,100)
that is frequently referenced with the fixed subscripts
table(m:n, p:q)
these references may be replaced by
REAL, DIMENSION(:, :), POINTER :: window
:
window => table(m:n, p:q)
The subscripts of window are 1:n-m+1, 1:q-p+1.
Similarly, for
tar%u
(as defined in Part 7), we can use, say,
taru => tar%u
to point at all the u components of tar, and subscript it as
taru(1, 2)
The subscripts are as those of tar itself.
(This replaces yet more of EQUIVALENCE.)
The source code of an extended example of the use of pointers to support a data structure is in appxg.f90