Fortran Pointers
A Fortran pointer is a typed view of a variable rather than a raw address: it can point at an existing target or own allocated storage, and it remembers its association status. Used well, pointers build linked structures and alias data without copying; used carelessly they break the optimizer's assumptions. This lesson maps the model and the pitfalls.
Pointer vs allocatable
The first decision is which tool fits the job. An allocatable variable owns its memory — assignment copies, leaving is automatic. A pointer references memory that someone else owns or that it allocates itself — assignment rebinds. Rule of thumb: if the variable only needs dynamic sizing, use allocatable; if it must alias an existing object or build a linked graph, use pointer. Allocatable is safer and the optimizer loves it; pointer is the occasionally necessary power tool.
program pointer_basics
implicit none
real, target :: value = 3.5 ! target: addressable storage
real, pointer :: p ! p is born "disassociated"
p => value ! pointer assignment: rebind, no copy
print *, p ! 3.5 through the pointer
p = 7.0 ! writes THROUGH the pointer
print *, value ! 7.0 — original variable changed
nullify (p) ! p disassociated again; value alive
end program pointer_basics
Fortran carefully distinguishes the two things other languages blur: pointer assignment (p => target) rebinds what the pointer looks at; ordinary assignment (p = value) through a pointer writes the pointed-to data. Mixing them is the number-one pointer bug: p = value when you meant a rebind silently overwrites the target instead.
When a pointer allocates its own storage, ordinary deallocate frees it, and the intrinsic associated(p) queries whether a pointer points at anything at all:
program pointer_allocate
implicit none
real, pointer :: p(:)
integer :: n = 100
allocate (p(n)) ! the pointer owns this block
p = 1.0 ! fills through the pointer
print *, associated(p), size(p) ! T 100
deallocate (p)
print *, associated(p) ! F — dangling references now averted
end program pointer_allocate
Targets, aliasing and the optimizer
A pointer may only point at variables declared target (or at pointer-allocated storage); the attribute tells the compiler the variable's address may escape. That single fact changes optimization: a subroutine receiving intent(inout) plus a pointer into the same object forces the compiler to assume the worst. The performance lesson measures exactly this cost. For now two habits protect you: keep pointer use inside small, isolated procedures, and never pass both a pointer and its target to the same call.
Linked structures
The classic self-referential type builds a linked list — each node holds data plus a pointer to the next node. Derived-type pointer components are where this model shines (and where allocatable components would deadlock):
program linked_list
implicit none
type :: node
integer :: value
type(node), pointer :: next ! link to the next node
end type node
type(node), target :: first, second, third
type(node), pointer :: cur
first%value = 1; second%value = 2; third%value = 3
first%next => second ! wire the chain by rebinding
second%next => third
third%next => null() ! terminate the chain
cur => first
do while (associated(cur)) ! walk until the null link
print '(a,i0)', 'node value: ', cur%value
cur => cur%next ! advance: whole traversal idiom
end do
end program linked_list
Real HPC code uses this shape rarely — arrays and allocatable containers beat pointers for both speed and readability — but file systems, symbol tables and parser internals still need it, and when they do, pointer components plus => wiring are the whole technique.
Pointer hygiene: always initialize pointers to => null(); test associated(p) before dereferencing; pair every allocate with a deallocate or nullify; and prefer allocatable to pointer wherever ownership (rather than aliasing) is what you actually want.