Skip to content

Far Pointer

A pointer representation that carries an explicit segment, address-space, or high-order context together with an offset, allowing dereference beyond the address region implied for an ordinary near pointer while making translation, arithmetic, comparison, and conversion context-sensitive.

Version
v2 · 2026-08-30 · History
Domain-specific #
1826
Origin domain
computer architecture
Subdomain
segmented and multiple-address-space memory models
Aliases
Far address pointer, Segmented pointer

Core Idea

A far pointer is a systems-programming pointer whose representation supplies address context that an ordinary near pointer leaves implicit. The recurring structure is not simply “a pointer to something distant.” It is context identifier plus location within that context: a segment value or selector and offset on segmented x86, an access-list-entry token (ALET) and offset in IBM z/OS access-register mode, or high-order address/page information combined with a lower-order program-memory address on large AVR devices. Dereference must interpret both parts through the target architecture's translation rules.[1][2][3]

Intel states the distinction exactly for non-64-bit x86 modes. A near pointer is a 16- or 32-bit offset within an implied segment; a far pointer is a logical address containing a 16-bit segment selector plus a 16- or 32-bit offset. The far form is required when the segment cannot be inferred from the operation or current memory model.[1] This distinction is architectural rather than merely lexical: the explicit segment component changes which address region is selected, how the processor validates access, and which machine instructions or calling sequences must be used.

The abstraction must be stated above any one x86 formula. In 8086 real mode, a segment value (s) and offset (o) translate, before bus-width behavior, as

\[ L=(s\ll 4)+o. \]

Because adjacent segment bases differ by only 16 bytes, many pairs can denote the same linear location. For example, 1234:0010 and 1235:0000 both yield 0x12350. By contrast, in x86 protected mode the segment field is a selector for a descriptor whose cached base, limit, type, and privilege attributes participate in translation and checking; treating the selector as a real-mode paragraph number is wrong.[1][4] IBM's current Metal C documentation provides a separate recurrence: its __far pointer combines an ALET identifying a secondary data space with an offset and is twice the size of a normal pointer.[5] The invariant is therefore functional, not a fixed bit layout: the pointer itself preserves enough non-default context to select an address region and an offset within it.

Structural Signature

The defining chain is:

partitioned or multiple address space → ordinary pointer with implicit context and limited reach → explicit context-bearing pointer → architecture-specific translation and validation → dereference of the selected region.

Six roles are mandatory:

  1. A partitioned address regime. Memory is divided into segments, spaces, banks, or pages such that an offset alone does not universally identify the target.
  2. A default context. Ordinary or near pointers are interpreted relative to an implied segment or address space. Without this contrast, “far” has no technical work to do.
  3. An explicit context component. The far representation carries or encodes the segment selector/value, address-space token, bank, or high-order address portion needed to leave the default region.
  4. An offset or lower-order location. A position within the selected context identifies the referent after translation.
  5. A context-aware dereference operation. Hardware, compiler-generated code, or a dedicated library operation installs or consumes the context and then accesses the target.
  6. Context-sensitive operations. Equality, ordering, arithmetic, casts, normalization, and ABI layout must respect the target architecture's rules; blindly applying flat-pointer rules can lose context or compare encodings rather than denotations.

The invariant is: a valid far-pointer dereference resolves the explicit context and the offset under one declared architecture and execution mode; neither component may be discarded unless the resulting ordinary pointer is proven to name the same accessible location. Exact widths, translation formulas, and permissible arithmetic are parameters of the architecture, not universal attributes of the abstraction.

What It Is Not

  • Not a synonym for Pointer. Every far pointer is a pointer, but most pointers in flat memory models carry one virtual address without a separately meaningful segment or space context. Far Pointer adds the near/far contrast, context-bearing representation, translation rules, and conversion hazards.
  • Not merely a large integer address. Some implementations expose a packed integer form, but the semantic distinction is that high-order/context information selects a region unavailable to the default pointer. A numeric cast that preserves bits need not preserve a valid typed dereference.
  • Not a physical address. On x86, segmentation first produces a linear address and paging may translate it further. In protected mode the selector identifies a descriptor rather than directly encoding a physical base.[4]
  • Not a far call or far jump. Those control-transfer operations consume a far logical address and may change the code segment; the pointer is the address representation, not the transfer instruction.
  • Not a huge pointer. Historical C implementations commonly distinguished __far from __huge. A huge-pointer discipline may normalize representations or adjust segment and offset during arithmetic so arrays can cross segment boundaries. Open Watcom explicitly documents far and huge as distinct qualified pointer forms.[6]
  • Not a based pointer. A based pointer keeps an offset compact while obtaining its base/segment from a separately designated source. Open Watcom presents it as a compromise between near-pointer efficiency and far-pointer reach; the context is not necessarily carried in each pointer value.[6]
  • Not contemporary “far memory” as a general storage tier. Remote memory, CXL-attached memory, and disaggregated memory may be called far because of latency or topology. They instantiate address indirection and tiering, but not this context-plus-offset pointer identity unless their programming representation actually carries the required non-default address-space context.

Scope of Application

The home domain is low-level programming for architectures whose addressable resources exceed, or are partitioned differently from, an ordinary pointer's implied region.

Segmented x86 is the canonical case. Intel's architectural definition covers near offsets and far logical addresses in non-64-bit modes. Historical 16-bit C memory models then made pointer size and default near/far status depend on whether code and data were assumed to fit within particular segments. Open Watcom documents small and big models, explicit __far overrides, far function and object pointers, and the cost/flexibility tradeoff.[1][6]

Protected x86 systems preserve the logical-address form while changing its meaning. The selector indexes a descriptor table entry; loading a segment register caches its base, limit, and access-control information. Far control transfers can additionally engage privilege and gate semantics. Therefore a debugger, loader, emulator, or binary-analysis tool must retain execution mode and descriptor context rather than decode every selector:offset pair with the real-mode shift-and-add formula.[4]

IBM z/OS Metal C in access-register mode uses current far-pointer terminology for access to secondary data spaces. IBM defines the upper component as an ALET and the lower component as an offset; only AR-mode code can dereference it directly, while comparison, casts, passing, and arithmetic have precisely documented restrictions.[2][5] This independent implementation establishes that Far Pointer is not merely an obsolete 8086 spelling.

Large AVR program memories provide a related embedded implementation. Microchip documents RAMPZ as extending the 16-bit Z pointer and pgm_get_far_address as obtaining a 24-bit address for objects beyond the ordinary 64 KiB reach; far program-memory access uses extended-load mechanisms.[3][7] The representation differs from x86, but the high-order-context-plus-lower-order-location problem is the same.

The abstraction does not extend to ordinary flat virtual addressing merely because one pointer numerically exceeds another. “Far” is technical only when it changes the representation or dereference regime relative to a near/default pointer.

Clarity

Naming Far Pointer isolates three questions that generic pointer vocabulary conflates: what region is selected, what offset is used within it, and what translation regime gives those fields meaning? That separation prevents the common error of reading a printed pair as a flat integer address. In 8086 real mode the segment contributes a base in 16-byte paragraphs. In protected mode a selector locates a descriptor. In z/OS AR mode an ALET selects a data space. The printed shape may look similar while the resolver is materially different.

The concept also clarifies why two levels of equality can diverge. Representation equality asks whether the stored context and offset fields match. Denotational equality asks whether the architecture resolves them to the same accessible byte or object. Real-mode x86 admits multiple segment-offset encodings for one linear location, so unequal bit patterns can denote the same byte. IBM instead specifies whole-pointer equality and warns that relational comparisons or arithmetic can be meaningless when ALETs differ.[5] The abstraction makes the required rule visible: equality and ordering cannot be chosen without stating the address model.

Manages Complexity

A flat-pointer story assumes that one compact value globally identifies storage. Partitioned architectures break that assumption: an offset may be meaningful only relative to a segment, bank, or data space. Far Pointer manages the resulting complexity by packaging the missing context into a transferable value. A function can receive, store, or return a reference to non-default storage without relying entirely on whichever segment register or implicit address space happens to be active at the call site.

This packaging moves complexity rather than eliminating it. The pointer becomes larger; dereference may require loading state or using specialized instructions; the ABI must specify field order and size; conversions can discard the context; arithmetic may be confined to the offset; and comparison may require normalization or a shared-context precondition. Those costs are coherent consequences of one design move—making context explicit. Open Watcom describes far pointers as more flexible but larger and slower than near pointers, while IBM specifies eight-byte far pointers in 31-bit mode and sixteen-byte far pointers in 64-bit mode.[6][5]

Abstract Reasoning

Far Pointer licenses a translation-first diagnostic. Given a failing or surprising access, do not begin with the nominal numeric address. First identify the execution mode and pointer kind; then split the representation into context and offset; resolve the context through the correct segment descriptor, ALET, page extension, or equivalent; apply bounds and privilege checks; and only then compare the resulting address with the intended object. This procedure predicts why a pair works in real mode but faults in protected mode, or why an IBM far pointer cannot be safely reduced to its offset.

It also licenses a conversion-loss proof obligation. Converting far to near removes information. Such a conversion is sound only if the context is the default context expected by the destination operation, or if an implementation-defined mapping proves the offset alone retains the referent. IBM explicitly says a far-to-normal cast extracts the offset and loses the ALET; unless the ALET was zero, the normal pointer is likely invalid.[5] The general inference is reusable: whenever a representation loses the context field, validity must be re-established rather than presumed.

A third move is representation-versus-denotation analysis. If equality is performed on raw fields, aliases with different representations may compare unequal; if arithmetic changes only the offset, crossing the segment or space boundary may fail or wrap rather than reach the next byte. The analyst therefore asks which operations are defined on representations, which on resolved locations, and which require operands to share context. This turns a scattered family of historical “memory model bugs” into explicit obligations on translation, normalization, and context preservation.

Knowledge Transfer

The abstraction transfers literally within systems programming wherever a default pointer lacks enough context. The exact context varies—x86 segment selector, z/OS ALET, AVR high-order program-memory address—but the role package remains recognizable: default context, explicit context extension, offset, context-aware dereference, and constrained operations. That lets compiler writers, emulator authors, binary-tool developers, embedded programmers, and mainframe programmers share one diagnostic vocabulary without pretending their encodings are identical.

Beyond computer architecture, the portable residue is already carried by broader nodes such as pointer, context, and indirection: a reference may require contextual resolution. Calling a citation or a remote object reference a far pointer would be analogy unless it implements the address-space role package. The domain-specific name should therefore not be promoted to a prime. Its transfer is strongest when concrete address partitioning and pointer operations survive intact.

Examples

Real-mode aliasing. Let (p=1234{:}0010) and (q=1235{:}0000). Using \(L=(s\ll4)+o\), both resolve to 0x12350. Their four stored bytes are different, yet their denotation is the same before any wrap behavior. Raw field equality therefore differs from resolved-address equality. The example is recomputed, not copied from the frozen article.

Protected-mode reinterpretation. Suppose selector 0x0023 identifies a user data descriptor with base 0x400000 and a valid offset 0x120. The logical address resolves initially to linear 0x400120, subject to descriptor limits, access rights, and later paging. Replacing the selector with 0x002B may select a different descriptor even though the offset is unchanged. Calculating 0x0023*16+0x120 would import the wrong real-mode rule.

z/OS secondary data space. An eight-byte AMODE-31 __far pointer consists of a four-byte ALET and four-byte offset. Two pointers with the same offset but different ALETs can identify locations in different data spaces. IBM therefore warns that pointer arithmetic applies to the offset and that relational results may lack meaning across unequal ALETs.[2][5]

AVR program memory beyond 64 KiB. A 16-bit Z pointer cannot by itself name all bytes on devices with larger program memory. RAMPZ supplies high address bits for ELPM, and Microchip's far-address macro produces a wider address for a linker-known object. This is far-pointer reasoning even though the compiler interface can present a packed 24-bit address rather than an x86-style printed pair.[3][7]

Structural Tensions

Reach versus compactness. Near pointers are smaller and can exploit an implied segment; far pointers reach additional regions by carrying context. The diagnostic is whether all referents fit the region guaranteed by the selected memory model. If yes, far representation is needless overhead; if no, near representation cannot name the required objects.

Explicitness versus ambient state. Carrying context makes the reference self-describing relative to an architecture, but dereference may still install that context in ambient registers. Based pointers choose the opposite tradeoff by keeping the pointer small and sourcing the base elsewhere. The diagnostic is whether references must remain valid when passed across callers with different default contexts.

Representation stability versus address continuity. Keeping the context field fixed makes arithmetic cheap but may stop at a segment boundary. Adjusting or normalizing both fields can support a more continuous view, but changes representation and comparison costs. The far/huge distinction in historical compilers expresses this tension.

Compatibility versus semantic residue. Win32 preserved many old LP... typedef names after near and far underlying pointer types converged. The vocabulary survived after the representational distinction disappeared.[8] The diagnostic is the actual ABI and compiler type, not a legacy prefix.

Structural–Framed Character

Far Pointer is strongly structural inside its home domain. Its mandatory context and offset roles causally determine translation, reachable storage, pointer width, conversion safety, and comparison behavior. One can predict faults or choose an implementation by manipulating those roles. It is also historically and architecturally framed: “segment,” “ALET,” “RAMPZ,” near/far memory models, and dereference instructions are concrete institutional and hardware vocabulary.

On a structural–framed scale it is mixed-structural, domain-bound. The explicit-context reference skeleton is intelligible beyond one processor family, as the Intel, IBM, and AVR recurrences show. But stripping address translation and pointer operations leaves generic contextual indirection, already represented by broader abstractions. The full far-pointer identity does not travel beyond systems that literally partition addressability.

Structural Core vs. Domain Accent

The skeletal core is: a reference that is insufficient under a default resolver becomes sufficient by carrying an explicit context discriminator alongside its within-context location. That structure helps compare segmented addressing, banked memories, capability-like context tags, and alternate data spaces.

The domain accent is decisive. A far pointer is stored in an ABI, manipulated by a compiler, and dereferenced by machine- or runtime-specific rules. Segment registers, descriptor tables, ALETs, byte offsets, extended load instructions, pointer casts, and memory models are not optional examples; they are what make the reference a pointer and what make it far. If those disappear, the remainder is Context plus Pointer or Indirection rather than a new substrate-neutral prime.

This boundary also explains autonomy from domain_specific:pointer. Pointer gives the genus—an address-bearing value followed to a referent. Far Pointer contributes a stable differentia with its own operation theory: an explicit non-default address context, near/far contrast, architecture-dependent translation, possible noncanonical encodings, and lossy context-dropping conversions. Those commitments recur independently and support diagnostics that generic Pointer does not entail.

The sole prospective DAG parent is live domain_specific:pointer, by strict subsumption: a far pointer remains a dereferenceable pointer value, while its explicit address context specializes the representation and operation rules. prime:indirection is an ancestor already reached through Pointer and need not receive a redundant direct edge.

prime:context illuminates why the extra component matters: an offset's denotation depends on a selected address context. This is a conceptual relation, not a second proposed parent, because Context alone does not entail address storage or dereference. domain_specific:memory_management is an operational neighbor concerning allocation, lifetime, reclamation, and address spaces; a far pointer can point into managed storage but does not itself allocate or reclaim it.

Relationships to Other Abstractions

Local relationship map for Far PointerParents appear above the current abstraction, mutual partners to the right, and children below. Node labels state whether each abstraction is prime or domain-specific; colors identify relation types.Far PointerDOMAINDomain-specific abstraction: Pointer — is a kind ofPointerDOMAIN

Current abstraction Far Pointer Domain-specific

Parents (1) — more general patterns this builds on

  • Far Pointer is a kind of Pointer Domain-specific

    The sole prospective DAG parent is live domain_specific:pointer, by strict subsumption: a far pointer remains a dereferenceable pointer value, while its explicit address context specializes the representation and operation rules.

Hierarchy paths (3) — routes to 3 parentless roots

Neighborhood in Abstraction Space

Far Pointer sits in a sparse region of the domain-specific corpus (84th percentile for distinctiveness): few abstractions share its structure, so a faithful description tends to retrieve it precisely.

Family — Unclustered & Miscellaneous (1565 abstractions)

Nearest neighbors

Computed from structural-signature embeddings · 2026-09-08

Not to Be Confused With

  • Pointer (domain_specific:pointer). Genus. Pointer supplies address-bearing indirection; Far Pointer adds explicit context required beyond an ordinary pointer's implied region.
  • Near pointer. Contrast class. It stores an offset interpreted in an implied segment or default address space.
  • Huge pointer. A compiler-specific normalized or arithmetic-enhanced segmented pointer form; not an exact alias for every far pointer.
  • Based pointer. An offset whose segment/base is designated separately, trading self-contained context for compactness.
  • Memory management. Allocation, lifetime, relocation, and reclamation policy. Far Pointer is an address representation and dereference regime.
  • Heap. A storage region or allocation discipline, not a context-bearing pointer form.
  • Null dereference. A failure caused by following a no-referent value. Far-pointer faults can instead arise from invalid selectors, bounds, privileges, lost context, or unsupported arithmetic even when the offset is nonzero.
  • Citation Pointer. A catalog abstraction for referential navigation in documents; its shared indirection is insufficient for segmented-memory identity.
  • Far call / far jump. Instructions that consume a far control-transfer address; they are operations on or users of the representation.
  • Far memory. A modern latency/topology category. It is not an alias unless the programming interface literally implements the context-plus-offset regime.

References

[1] Intel Corporation. Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 1: Basic Architecture, especially “Pointer Data Types” and segmentation chapters. registry ↩a ↩b ↩c ↩d

[2] IBM. “AR-mode programming support,” Enterprise Metal C for z/OS. registry ↩a ↩b ↩c

[3] Microchip Technology. “Extended Z-Pointer Register,” AVR device documentation. registry ↩a ↩b ↩c

[4] Intel Corporation. Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 3A: System Programming Guide, Part 1, segmentation, descriptors, and protected-mode translation. registry ↩a ↩b ↩c

[5] IBM. “The __far type qualifier,” Enterprise Metal C for z/OS. registry ↩a ↩b ↩c ↩d ↩e ↩f

[6] Open Watcom Project. Open Watcom 2.0 C Language Reference, memory models, __far, __huge, and based pointers. registry ↩a ↩b ↩c ↩d

[7] Microchip Technology. pgm_get_far_address,” AVR-LibC documentation. registry ↩a ↩b

[8] Raymond Chen. “Why do I sometimes see redundant casts before casting to LPARAM?”, Microsoft, 2004. registry