ReviseAlgo Logo

Pointers and Memory Management

Pointers and Arrays

The deep relationship between pointers and arrays in C++

Interview: Fundamental C++ memory model — array decay, pointer arithmetic, and sizeof are common interview questions

Pointers and Arrays

In C++, arrays and pointers have an intimate relationship inherited from C. An array name, in most contexts, decays to a pointer to its first element. This decay is implicit and silent — it's one of the most common sources of subtle bugs and is a frequent interview topic.

Array Decay

When an array is passed to a function, it decays to a T* pointing to the first element. The size information is completely lost. This is why C-style functions always require a separate size parameter: void process(int* arr, int n). The only contexts where decay does NOT happen: sizeof, & (address-of), and binding to a typed array reference.

Equivalence of Expressions

Given int arr[] and int* ptr = arr, the following are all equivalent: arr[i], *(arr + i), ptr[i], *(ptr + i), and even i[arr] (the subscript operator is commutative). This equivalence is a direct consequence of how pointer arithmetic and array indexing are defined.

sizeof — The Key Difference

sizeof(array) gives the total size of the array in bytes. sizeof(pointer) gives the size of the pointer itself (8 bytes on 64-bit). Once an array has decayed, you can no longer recover its size — this is the critical distinction interviewers test.

Interview Corner

Q: What does array decay mean and what information is lost?

A: Array decay is the implicit conversion of an array to a pointer to its first element. The lost information is the array's size — once decayed, the pointer cannot tell you how many elements it points to. This forces C APIs to pass size as a separate parameter. std::array and std::vector solve this by storing size alongside the data.

Q: What is the output of sizeof on an array vs pointer to that array?

A: int arr[5]; sizeof(arr) = 20 (5 × 4 bytes). int* ptr = arr; sizeof(ptr) = 8 (64-bit pointer size). After decay: void f(int arr[]) { sizeof(arr); } — the parameter is actually int*, so sizeof gives 8, not 20. This surprises many developers.

Common Pitfalls

  • sizeof inside a function accepting an array: The most common sizeof pitfall — sizeof(arr) / sizeof(arr[0]) gives 2 (pointer/int) inside a function, not the array element count.
  • Out-of-bounds via pointer arithmetic: Accessing ptr + n where n ≥ array size is undefined behavior — reads garbage or causes a segfault.

Best Practices

  • Use std::array or std::vector — they carry their size and don't decay.
  • When passing C-style arrays to functions, accept a const T (&arr)[N] reference template to preserve size: template<std::size_t N> void process(int (&arr)[N]).