Near, Far, and Huge Pointers in C

Near, Far, and Huge Pointers in C Language with Examples

In this article, I will discuss the Near, Far, and Huge Pointers in C Language with Examples. Please read our previous articles discussing Function Pointer in C Language with Examples.

Near, Far, and Huge Pointers in C Language:

In C programming, especially in the context of 16-bit architectures like the old x86 real mode, pointers are often categorized into three types: Near, Far, and Huge Pointers. These types reflect how memory addresses are accessed in segmented memory models. Modern computing environments typically don’t use these types of pointers due to the prevalence of flat memory models.

Near Pointer in C Language

A near pointer is a 16-bit pointer in a segmented memory model that can only access memory within the current segment. It can’t access data outside its segment, typically limited to 64KB. They are used in small models where data and code are expected to be within the same segment.

Example:

In a 16-bit environment, a near pointer was the default type of pointer and could only address up to 64KB of memory within the current segment:

int main() {
    int a = 10;
    int *nearPtr = &a; // In a 16-bit environment, this is a near pointer by default

    printf("%d\n", *nearPtr); // Outputs the value of a, i.e., 10
    return 0;
}
Limitation

A near pointer could not access memory beyond its current segment:

void someFunction() {
    int localVar = 20;
    // nearPtr is a near pointer to localVar
}

int main() {
    int *nearPtr;
    someFunction();
    // Here, nearPtr would be dangling or invalid as it tries to point to a local variable that's out of scope
    return 0;
}
Key Points of Near Pointer:
  • Definition: A near pointer is a 16-bit pointer in the segmented memory model that can directly address up to 64KB of memory.
  • Limitation: It can only access data within the current segment because it doesn’t include a segment selector.
  • Usage: In a program, a near pointer is often declared a regular pointer. For example, int *ptr; in a 16-bit environment would be a near pointer by default.

Far Pointer in C Language

A far pointer is a 32-bit pointer used in 16-bit segmented memory models. It consists of a segment and an offset, allowing it to access memory across different segments. They are essential in medium or large memory models where data might be in different segments.

Far Pointer Example: Accessing Video Memory

In older PCs, video memory was often accessed directly for graphical operations. A far pointer could be used to write characters directly to the screen.

#include <dos.h>

int main() {
    // Video memory for text mode is typically at 0xB800:0000
    char far *video_memory = (char far *)MK_FP(0xB800, 0x0000);

    // Writing 'A' character with attribute byte to video memory
    *video_memory = 'A';         // character
    *(video_memory + 1) = 0x07;  // attribute (light gray on black)

    return 0;
}
Far Pointer Example: Manipulating Memory in Different Segments

Far pointers can be used to manipulate data in different memory segments, essential in large applications exceeding the 64KB segment limit.

#include <dos.h>

void manipulateMemory() {
    unsigned char far *ptr1;
    unsigned char far *ptr2;

    // Allocating memory in different segments
    ptr1 = (unsigned char far *)farmalloc(1000);
    ptr2 = (unsigned char far *)farmalloc(1000);

    if (ptr1 && ptr2) {
        // You can now manipulate memory across segments
        // For example, copy data from one far memory location to another
        _fmemcpy(ptr2, ptr1, 1000);
    }

    // Free memory
    farfree(ptr1);
    farfree(ptr2);
}

int main() {
    manipulateMemory();
    return 0;
}

Key Points of Far Pointer:
  • Definition: A far pointer is a 32-bit pointer in a segmented memory model, where the first 16 bits identify the segment and the next 16 bits specify the offset within that segment.
  • Capability: It can access memory outside the current segment, allowing it to address more than a near pointer.
  • Usage: Declared specifically with the far keyword, e.g., int far *ptr;. It addresses up to 1MB of memory in systems like MS-DOS.

Huge Pointer in C Language

Huge pointers are similar to far pointers but with one key difference: arithmetic on huge pointers takes segment boundaries into account, automatically adjusting the segment part of the address as needed. They are useful in large data models, especially for data that spans multiple segments.

Huge Pointer Example: Basic Usage
#include <dos.h> // Necessary for huge pointers in DOS

int main() {
    int huge *hPtr;
    int a = 10;

    hPtr = (int huge *)&a; // Cast the address of 'a' to a huge pointer
    *hPtr = 20;            // Now 'a' is 20

    printf("%d\n", a);     // Outputs 20
    return 0;
}
Huge Pointer Example: Pointer Arithmetic Across Segments

Huge pointers automatically handle segment boundary crossing during pointer arithmetic:

#include <dos.h>
#include <stdlib.h>

int main() {
    char huge *hPtr1, huge *hPtr2;

    // Allocate a large block of memory
    hPtr1 = (char huge *)halloc(70000UL, sizeof(char));

    hPtr2 = hPtr1 + 69999; // Pointer arithmetic crosses segment boundary

    *hPtr1 = 'A';
    *hPtr2 = 'Z';

    printf("%c %c\n", *hPtr1, *hPtr2); // Outputs 'A Z'

    hfree(hPtr1); // Free the allocated memory
    return 0;
}
Key Points of Huge Pointer:
  • Definition: Huge pointers are similar to far pointers but have one key difference in handling segment wraparounds.
  • Special Feature: When huge pointer arithmetic crosses the 64KB segment boundary, the pointer’s segment and offset parts are adjusted. Unlike far pointers, where only the offset is changed, potentially causing a wraparound within the same segment.
  • Usage: Declared with the huge keyword, e.g., int huge *ptr;.
Modern Context

Using near, far, and huge pointers in modern computing is largely obsolete. These concepts were relevant in the 16-bit computing era (like DOS programming) with segmented memory models. Modern operating systems and processors, with their flat memory models, do not require such distinctions, and standard C does not have these keywords. In 32-bit and 64-bit architectures, all pointers are typically the same size and can address any location in the memory space.

Example Code for Historical Context
#include <stdio.h>
#include <dos.h>

void main() {
    char far *fPtr;
    fPtr = (char far *) MK_FP(0xB800, 0x0000); // Pointing to video memory

    // Writing directly to video memory
    *fPtr = 'H';
    *(fPtr + 2) = 'i';

    // No actual near and huge pointer operations since they are mostly obsolete
}

This code is a DOS-era example of manipulating video memory directly, common in systems like the IBM PC. Note that such code will not compile on modern systems without a specific old-fashioned DOS compiler and environment.

Differences Between Near, Far, and Huge Pointers in C Language

Near, Far, and Huge pointers were concepts used in the segmented memory models of older 16-bit systems like MS-DOS. Here’s a breakdown of their differences:

Near Pointers in C Language
  • Size: Typically, 16 bits.
  • Range: Can access up to 64KB of memory within the current segment.
  • Segmentation: They do not include a segment selector; they only have an offset component relative to the current segment base.
  • Use Case: Default pointer type in many 16-bit environments; limited to accessing data within a single segment.
  • Limitation: Cannot access memory outside the segment they are defined in.
Far Pointers in C Language
  • Size: Typically, 32 bits (16 bits for the segment and 16 for the offset).
  • Range: Can access a larger memory range (up to 1MB in systems like MS-DOS) across different segments.
  • Segmentation: Include both segment and offset parts, allowing them to point to an address in any segment.
  • Use Case: Used when a program needs to access data outside the current segment.
  • Limitation: Pointer arithmetic only affects the offset part; if it crosses a 64KB boundary, it wraps within the same segment.
Huge Pointers in C Language
  • Size: Similar to far pointers, 32 bits (16 for segment, 16 for offset).
  • Range: Same as far pointers, but handle pointer arithmetic differently.
  • Segmentation: Like far pointers, they include segment and offset parts.
  • Use Case: Useful for operations on large arrays or buffers, especially when crossing segment boundaries, is expected.
  • Special Feature: Automatically adjust both segment and offset when pointer arithmetic crosses a 64KB segment boundary, preventing wraparound within the same segment.
Key Differences Between Near, Far, and Huge Pointers in C:
Scope of Access:
  • Near pointers: Limited to the current segment (64KB).
  • Far pointers: Can access different segments but with segment:offset limitations.
  • Huge pointers: Can access across segments with automatic adjustment for overflow in the offset.
Pointer Arithmetic:
  • Near pointers: Simple, as it’s within a single segment.
  • Far pointers: Limited; arithmetic overflow does not affect the segment part.
  • Huge pointers: Complex; arithmetic overflow adjusts the segment part.
Memory Model Suitability:
  • Near pointers: Suitable for small memory models.
  • Far pointers: Suitable for medium or large memory models.
  • Huge pointers: Ideal for very large data models spanning multiple segments.
Modern Relevance
  • In contemporary 32-bit or 64-bit flat memory models, these distinctions are irrelevant.
  • Near, far, and huge pointers were mainly relevant in older systems and were not used in modern C programming environments.
  • Understanding these concepts is more of historical interest or for working with legacy systems that used a segmented memory model.

In the next article, I will discuss Pointer to Structure in C Language with Examples. In this article, I try to explain Near, Far, and Huge Pointers in C Language with Examples. I hope you enjoy this article, “Near, Far, and Huge Pointers in C Language with Examples.” I would like to have your feedback. Please post your feedback, questions, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *