No history yet

Advanced Pointer Mastery

Beyond Simple Addresses

You already know that pointers store memory addresses. But they aren't just static signposts. You can perform arithmetic on them to navigate through blocks of memory, like stepping through houses on a street. When you add an integer to a pointer, you aren't just adding a number to an address. You're telling the pointer to move forward by a specific number of elements.

The compiler automatically scales the arithmetic by the size of the data type the pointer points to. Adding 1 to an int pointer moves it 4 bytes (on most systems), while adding 1 to a char pointer moves it just 1 byte.

#include <stdio.h>

int main() {
    int numbers[] = {10, 20, 30, 40};
    int *ptr = numbers; // ptr points to the first element, 10

    // Move to the third element (index 2)
    ptr = ptr + 2;

    printf("Value at ptr: %d\n", *ptr); // Prints 30
    printf("Address ptr points to: %p\n", ptr);

    // Move back one element
    ptr--;
    printf("Value after decrement: %d\n", *ptr); // Prints 20

    return 0;
}

This scaling is what makes pointer arithmetic so powerful and intuitive for array manipulation. Instead of calculating byte offsets manually, you can think in terms of array indices. The expression *(ptr + i) is equivalent to ptr[i].

Pointers to Pointers

Just as a pointer can hold the address of a variable, it can also hold the address of another pointer. This is called a double pointer, or a pointer to a pointer. It introduces another level of .

Why would you need this? A classic use case is when you want a function to modify a pointer that was passed into it. In C, arguments are passed by value. If you pass a pointer to a function, you're passing a copy of the pointer's address. The function can change what the pointer points to, but it can't change the original pointer itself.

To change the original pointer, you must pass its address—a pointer to a pointer.

#include <stdio.h>
#include <stdlib.h>

// This function allocates memory and modifies the caller's pointer.
void allocateMemory(int **ptr_address) {
    // Allocate space for 5 integers
    *ptr_address = (int *)malloc(5 * sizeof(int));
    if (*ptr_address == NULL) {
        // Allocation failed
        return;
    }
    // Initialize memory
    for (int i = 0; i < 5; i++) {
        (*ptr_address)[i] = i * 10;
    }
}

int main() {
    int *my_ptr = NULL; // Start with a null pointer

    // Pass the address of my_ptr
    allocateMemory(&my_ptr);

    if (my_ptr != NULL) {
        printf("First element: %d\n", my_ptr[0]); // Prints 0
        free(my_ptr); // Always free allocated memory
    }

    return 0;
}

Pointers That Execute

Pointers can also store the address of executable code—that is, a function. A function pointer is a variable that points to a function with a specific signature (return type and parameter types). This allows you to treat functions like any other data: you can pass them to other functions, store them in arrays, and call them dynamically.

The syntax can look a bit strange at first. The key is to wrap the pointer's name and the asterisk in parentheses.

// A regular function
int add(int a, int b) {
    return a + b;
}

// A pointer that can hold the address of a function
// that takes two ints and returns an int.
int (*operation)(int, int);

// Assign the address of the 'add' function
operation = &add; // or simply operation = add;

// Call the function through the pointer
int result = (*operation)(5, 3); // result is 8
int result2 = operation(10, 2);  // Alternate syntax, result2 is 12

This feature is incredibly useful for creating generic algorithms. Imagine a sorting function that can sort any data type. How does it know how to compare two elements? You tell it by passing a function pointer to a comparison function.

Ready to test your understanding of these advanced pointer concepts? This quiz will cover pointer arithmetic, double pointers, and function pointers.

Quiz Questions 1/5

Given the following code, what will be printed?

int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr;
ptr = ptr + 3;
printf("%d", *ptr);
Quiz Questions 2/5

In C, what is the primary reason to pass a pointer-to-a-pointer (e.g., void **ptr) to a function?

Mastering these pointer techniques unlocks a deeper level of control and flexibility in C, allowing you to build highly efficient and modular systems.