Intermediate 11 min

Pointers and Arrays

Understand the deep relationship between pointers and arrays, array decay, and pointer notation for array access

Discover the intimate connection between pointers and arrays, and learn why array names decay to pointers in most contexts.

A Simple Example

#include <iostream>

int main() {
    int numbers[5] {10, 20, 30, 40, 50};

    // Array name behaves like a pointer to first element
    std::cout << "Array name: " << numbers << "\n";  // Address
    std::cout << "First element address: " << &numbers[0] << "\n";  // Same address

    // These are equivalent:
    int* ptr{numbers};  // No & needed! numbers decays to pointer
    int* ptr2{&numbers[0]};  // Explicit address of first element

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

    // Pointer arithmetic works with array names
    std::cout << "*(numbers + 2): " << *(numbers + 2) << "\n";  // 30
    std::cout << "numbers[2]: " << numbers[2] << "\n";  // 30 (same!)

    return 0;
}

Breaking It Down

Array Decay: Arrays Convert to Pointers

  • What it means: In most contexts, an array name decays to a pointer to its first element
  • When it happens: Function parameters, assignments to pointers, arithmetic operations
  • When it doesn't: sizeof(array) and &array don't decay - they use the whole array
  • Remember: int arr[5] decays to int* pointing to arr[0]

Array Name as Pointer: int* ptr = arr;

  • No & needed: int* ptr{numbers}; works because array name IS a pointer
  • Equivalent forms: ptr = numbers and ptr = &numbers[0] are identical
  • Can dereference: *numbers gives first element, just like numbers[0]
  • Remember: The array name is a constant pointer - you can't reassign it

Pointer Notation for Arrays: *(arr + i) = arr[i]

  • Equivalence: arr[i] is syntactic sugar for *(arr + i)
  • Why it works: Pointer arithmetic lets you navigate through array elements
  • Both work: You can use ptr[2] even though ptr is a pointer, not an array
  • Remember: This reveals that array indexing is just pointer arithmetic

Passing Arrays to Functions

  • Always decays: void func(int arr[]) receives a pointer, not a copy of the array
  • Same signatures: void func(int arr[]) and void func(int* arr) are identical
  • No size info: sizeof(arr) in function gives pointer size, not array size
  • Remember: Always pass array size as a separate parameter

Why This Matters

  • Understanding the pointer-array connection is crucial for working with C-style arrays, passing arrays to functions, dynamic memory allocation, and interfacing with C libraries.
  • This knowledge forms the foundation for advanced memory management and data structure implementation.

Critical Insight

When you pass an array to a function, it always decays to a pointer. This means the function receives a copy of the pointer (which is cheap), not a copy of the entire array. This is why functions can modify the original array and why you must pass the size separately!

Think of it like giving someone your home address instead of physically moving your house to them - they can visit and change things, but you're just sharing a reference.

Best Practices

Pass array size as parameter: Always pass the size alongside the array: void func(int arr[], int size). You can't rely on sizeof in functions.

Use pointer syntax when appropriate: If you're treating it as a pointer, declare it as int* arr to make intent clear.

Consider std::array or std::vector: Modern C++ containers don't decay and know their own size. Use them when possible.

Document array size requirements: If a function expects a minimum array size, document it clearly or use std::array with template.

Common Mistakes

Assuming sizeof works in functions: sizeof(arr) inside a function gives pointer size, not array size. Always pass size separately.

Trying to modify array name: You can't write arr = otherArray; because array names are constant pointers.

Confusing pointer to array vs pointer to element: int (*p)[5] is a pointer to array of 5 ints, different from int* p which points to one int.

Forgetting array decay in functions: Functions can modify the original array because they receive a pointer, not a copy.

Debug Challenge

This function cannot get the array size because arrays decay to pointers. Click the highlighted line to fix it:

1 #include <iostream>
2
3 void printSize(int arr[]) {
4 int size = sizeof(arr) / sizeof(arr[0]); // Wrong!
5 std::cout << "Size: " << size << "\n";
6 }

Quick Quiz

  1. What does arr decay to when passed to a function?
Pointer to first element
Copy of the array
Reference to the array
  1. Are void func(int arr[]) and void func(int* arr) equivalent?
Yes, they're identical
No, they're different
Only if arr has known size
  1. What's the value of sizeof(arr) inside void func(int arr[100])?
8 (pointer size on 64-bit system)
400 (100 * 4 bytes)
100

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