Array of Pointers vs Pointer to an Array in C
In C programming, the distinction between an array of pointers and a pointer to an array hinges on operator precedence, memory layout, and pointer arithmetic. An array of pointers is a collection where each element stores a memory address pointing to data located elsewhere, whereas a pointer to an array is a single pointer variable that holds the address of an entire contiguous array block. This article breaks down the operational differences between both constructs, examining their declaration syntax, memory footprint, address calculations, and typical use cases.
Syntax and Operator Precedence
The difference in declaration arises from the precedence of the array
subscript operator [] over the dereference operator
*.
Array of Pointers:
int *arr[5];Because
[]has higher precedence than*,arris evaluated first as an array of 5 elements. The*indicates that each element in this array is a pointer to an integer (int *).Pointer to an Array:
int (*ptr)[5];Parentheses override default operator precedence. The
*ptris evaluated first, meaningptris a single pointer. The[5]indicates that it points specifically to an array of 5 integers.
Memory Allocation and Layout
The memory footprint and layout of these two constructs differ significantly:
int *arr[5]: Allocates memory for 5 separate pointer variables on the stack. On a 64-bit system, this consumes5 * 8 = 40 bytes. The data items these pointers point to do not need to be contiguous and can reside anywhere in memory (e.g., separate heap allocations or independent variables).int (*ptr)[5]: Allocates memory for a single pointer variable. On a 64-bit system, this occupies only 8 bytes. It points to a single, contiguous block of memory containing 5 integers (5 * 4 = 20 bytes).
Pointer Arithmetic
The most critical operational difference occurs during pointer arithmetic, as the C compiler scales increments based on the type of data being pointed to.
For an array of pointers
arr:arr + 1;The expression
arrdecays into a pointer to its first element (a pointer to anint *). Adding1advances the memory address by the size of a pointer (sizeof(int *), typically 8 bytes).For a pointer to an array
ptr:ptr + 1;Adding
1advances the address by the total size of the entire array it points to:5 * sizeof(int)(typically 20 bytes). Instead of moving to the next element, it steps over the entire 5-element array to point to where the next contiguous 5-element array would begin.
Accessing and Dereferencing Data
The mechanics for reading and writing data reflect their differing structures:
- Array of Pointers:
arr[i]accesses the pointer stored at indexi.*arr[i]orarr[i][0]dereferences that pointer to read the value it references.*(arr[i] + j)orarr[i][j]accesses thej-th element of the sequence pointed to by thei-th pointer.
- Pointer to an Array:
*ptrdereferences the pointer to yield the underlying array, which immediately decays into a pointer to the first element (&(*ptr)[0]).(*ptr)[i]accesses thei-th element within the array. The parentheses around*ptrare required to dereference the pointer before indexing into the array elements.
Common Use Cases
- Arrays of Pointers are ideal for handling dynamic,
non-contiguous data collections such as "ragged" or "jagged" arrays
(where rows have varying lengths), string arrays
(
char *argv[]), and sorting mechanisms where swapping pointers is more efficient than copying large data blocks. - Pointers to Arrays are primarily used when passing
multidimensional arrays with fixed secondary dimensions to functions
(e.g.,
void process_matrix(int (*matrix)[10], int rows)), preserving row-length boundary information for compiler index calculations.