Chapter 11 — Key Takeaways (Pointers, Targets, and Dynamic Data Structures)

A one-page reference. The whole chapter reduces to two sentences: => moves the alias and = writes the value; and prefer allocatable, reaching for pointer only when you truly must.

The two assignments (memorize this first)

Statement Name Effect
p => a pointer assignment makes p an alias for a; changes what p refers to, no value copied
p = a value assignment if p is associated, copies a's value through p into its target

Confusing these corrupts data silently. => relocates the sticky note; = writes on the page under it.

Declaring pointers and targets

real(dp), target  :: a          ! a may be pointed at
real(dp), pointer :: p => null() ! ALWAYS initialize: never leave a pointer undefined
p => a                            ! associate
  • A pointer may only point at an object with the target attribute (or another pointer).
  • An object without target is assumed un-aliased, which the compiler optimizes around — so do not add target unless you need it.

Association status and the two hazards

Status Meaning associated(p)
associated valid alias for a target / allocated memory .true.
disassociated explicitly points at nothing (nullify, => null()) .false.
undefined never initialized — do not query undefined behavior
Hazard What it is Fix
Undefined pointer never given a status initialize => null() / nullify at birth
Dangling pointer aliases freed/out-of-scope memory; may still look associated nullify every alias after deallocate

Intrinsics and statements introduced

Name What it does
associated(p) is p associated with any target? (illegal on an undefined pointer)
associated(p, tgt) is p associated with this specific target?
nullify(p) set p to the disassociated state
=> null() initialize/assign a pointer to disassociated
is_contiguous(a) does a actually occupy contiguous memory? (Fortran 2008)
move_alloc(from, to) $O(1)$ transfer of an allocation; leaves from deallocated

allocatable vs pointer — the decision

Prefer allocatable when… Reach for pointer only when…
you own the data (the usual case) you must alias an existing object
you want automatic deallocation you need a genuine linked structure (and an index-array won't do)
you want no dangling, no leaks you need a polymorphic container (class, select type)
you want full no-aliasing optimization you need a callback (procedure pointer)
the array is a derived-type component you must handle a C address (type(c_ptr), c_f_pointer)

The rule: prefer allocatable; use pointer only for aliasing, links, polymorphism, callbacks, or C interop.

Linked structures — the safe teardown

p => head
do while (associated(p))
  nxt => p%next     ! SAVE next before...
  deallocate(p)     ! ...freeing the node
  p => nxt
end do
nullify(head)
  • Never read a node after you deallocate it.
  • In Fortran, prefer an array or an index-based structure over raw pointer links — contiguity prefetches and vectorizes; pointer-chasing does neither.

The contiguous attribute

real(dp), pointer, contiguous       :: col(:)   ! promise: a solid block
real(dp), intent(in), contiguous    :: u(:,:)   ! same promise on a dummy (Ch. 29)
  • A promise the array is one unbroken block (no strides) — licenses vectorization; changes no results.
  • Column-major fact: a column a(:,j) is contiguous; a row a(i,:) is not.
  • Break the promise (aim it at a strided slice) and the program is nonconforming.

Procedure pointers (callbacks) — one line

procedure(unary), pointer :: f => null()
f => square;  y = f(3.0_dp)   ! choose behavior at run time

Numbers and rules worth remembering

  • Growable array = allocatable store + logical-size n, doubled on overflow → $O(1)$ amortized append (arithmetic growth would be $O(n)$).
  • A linked list of $n$ int nodes (16 B/node) costs ~ the memory of a plain 4-byte-int array.
  • After deallocate, every alias must be nullified — the language tracks only the one you named.

Project piece added this chapter

Not new code for the solver — a justified decision: field_t stores its grid as real(dp), allocatable :: u(:,:), never a pointer, for automatic deallocation, no dangling, and the no-aliasing optimization the Chapter 24 stencil relies on (foreshadowing Chapter 27). contiguous is applied to a dummy argument, not the field itself, when Chapter 29 optimizes the sweep.