Intermediate 11 min

Pointer Arithmetic

Master pointer arithmetic to navigate through memory, increment and decrement pointers, and traverse arrays efficiently

Learn how to perform arithmetic operations on pointers to navigate through memory and process arrays efficiently.

A Simple Example

#include <iostream>

int main() {
    int numbers[5] {10, 20, 30, 40, 50};
    int* ptr{numbers};  // Points to first element

    std::cout << "First element: " << *ptr << "\n";  // 10

    ptr++;  // Move to next element (adds sizeof(int) bytes)
    std::cout << "Second element: " << *ptr << "\n";  // 20

    ptr++;  // Move to next element
    std::cout << "Third element: " << *ptr << "\n";  // 30

    ptr += 2;  // Jump forward 2 elements
    std::cout << "Fifth element: " << *ptr << "\n";  // 50

    // Pointer subtraction
    int* start{numbers};
    int* end{&numbers[4]};
    int distance = end - start;  // Number of elements between
    std::cout << "Distance: " << distance << "\n";  // 4

    return 0;
}

Breaking It Down

Pointer Increment/Decrement: ptr++ and ptr--

  • What it does: ptr++ moves pointer forward by one element (not one byte!)
  • Type-aware: For int*, adds 4 bytes; for double*, adds 8 bytes
  • Post vs pre: ptr++ increments after use, ++ptr increments before
  • Remember: The compiler handles the size automatically based on pointer type

Pointer Addition/Subtraction: ptr + n and ptr - n

  • What it does: ptr + 3 moves forward 3 elements, ptr - 2 moves back 2
  • Creates new pointer: ptr + 3 doesn't modify ptr, it creates a new pointer value
  • Equivalent to indexing: *(ptr + i) is the same as ptr[i]
  • Remember: Addition/subtraction works in element units, not bytes

Pointer Difference: ptr2 - ptr1

  • What it does: Gives number of elements between two pointers
  • Returns ptrdiff_t: A signed integer type (can be negative)
  • Only valid on same array: Both pointers must point within the same array
  • Remember: Result is element count, not byte difference

Array Indexing is Pointer Arithmetic: arr[i] = *(arr + i)

  • Equivalence revealed: arr[3] is syntactic sugar for *(arr + 3)
  • Commutative property: arr[i] = i[arr] (weird but valid!)
  • Works with pointers: You can use ptr[i] notation even on pointer variables
  • Remember: This is why array access is so fast - it's just pointer math

Why This Matters

  • Pointer arithmetic is fundamental to efficient array processing, implementing data structures, low-level memory operations, and understanding how array indexing actually works behind the scenes.
  • It's a powerful tool that gives you fine-grained control over memory access patterns.

Critical Insight

Array indexing arr[i] is actually syntactic sugar for pointer arithmetic *(arr + i)! When you write arr[3], the compiler translates it to *(arr + 3). This is why arrays and pointers are so closely related in C++.

This also explains why you can write bizarre but valid code like 3[arr] - it's just *(3 + arr), which is the same as *(arr + 3) due to commutativity!

Best Practices

Prefer array indexing for clarity: Use arr[i] instead of *(ptr + i) unless pointer arithmetic is central to the algorithm.

Check bounds before arithmetic: Ensure pointer arithmetic doesn't go out of array bounds. Out-of-bounds access is undefined behavior.

Use iterators in modern C++: For containers like std::vector, use iterators which are safer than raw pointer arithmetic.

Document pointer relationships: Make it clear when pointers are expected to point within the same array for subtraction.

Common Mistakes

Incrementing without considering type size: Pointer increment automatically scales by element size, not bytes. ptr++ on int* adds 4 bytes, not 1.

Going out of bounds: ptr + 10 might point beyond the array, causing undefined behavior when dereferenced.

Pointer arithmetic on unrelated pointers: Subtracting pointers not from the same array gives meaningless results.

Forgetting parentheses with dereference: *ptr++ increments ptr, then dereferences. Use (*ptr)++ to increment the value.

Debug Challenge

This code has a pointer arithmetic error. Click the highlighted line to fix it:

1 #include <iostream>
2
3 int main() {
4 int arr[5] {10, 20, 30, 40, 50};
5 int* ptr{arr};
6 ptr + 3;
7 std::cout << *ptr << "\n";
8 return 0;
9 }

Quick Quiz

  1. If int* p points to arr[0], what does p + 3 point to?
arr[3]
3 bytes after arr[0]
Address of p plus 3
  1. What is the value of distance in this code?
int* p1{&arr[1]};
int* p2{&arr[10]};
int distance = p2 - p1;
9
36 (assuming sizeof(int) is 4)
10
  1. What does arr[i] translate to in terms of pointer arithmetic?
`*(arr + i)`
`arr + i`
`&arr[i]`

Practice Playground

Time to try out what you just learned! Play with the example code below, experiment by making changes and running the code to deepen your understanding.

Lesson Progress

  • Fix This Code
  • Quick Quiz
  • Practice Playground - run once