Arrays and Pointers
Introduction
A variable represents a single location in memory. A collection of variables in a contiguous address space (i.e no gaps) is known as an array. Arrays and pointers are closely related in C because array names frequently decay to pointers (more on this below).
A conceptual diagram of an int array with 7 elements named array:
array:
[ array[0] ][ array[1] ][ array[2] ][ array[3] ][ array[4] ][ array[5] ][ array[6] ]
^ ^ ^ ^ ^ ^ ^
&array[0] &array[1] &array[2] &array[3] &array[4] &array[5] &array[6]
Arrays are zero‑indexed: the first element is array[0].
Arrays and pointers
Arrays and pointers are linked because array names often convert to pointers to their first element in expressions. You can index arrays with [] or use pointer arithmetic with * and +.
#include <stdio.h>
int main(void) {
int array[5] = {100, 101, 102, 103, 104};
// Print values and their addresses
for (int i = 0; i < 5; i++) {
printf("array[%d] = %d\n", i, array[i]);
}
for (int i = 0; i < 5; i++) {
printf("address of array[%d] = %p\n", i, &array[i]);
}
// 'array' in an expression is equivalent to &array[0]
printf("array (decays to &array[0]) = %p\n", array);
printf("&array[0] = %p\n", &array[0]);
// Use pointers to access array elements
for (int i = 0; i < 5; i++) {
printf("*(array + %d) = %d\n", i, *(array + i));
}
return 0;
}
What to notice
- Consecutive element addresses increase by
sizeof(int). array(in most expressions) is the same address as&array[0].array[i]is the same as*(array + i).
Important exceptions (no decay):
sizeof arraygives the total bytes of the array object (e.g.,5 * sizeof(int)), not a pointer size.&arraygives type pointer to the entire array (e.g.,int (*)[5]), notint *.- In the declaration itself,
int array[5];is an array, not a pointer.
Passing arrays to functions
Functions can accept arrays and can modify them. However, in a function parameter list, int array[] is rewritten by the compiler as int *array. That means the function receives a pointer, so you must pass the length separately if needed.
#include <stdio.h>
// Read-only access (note 'const')
int sum_of_array(const int array[], int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += array[i];
}
return sum;
}
// Modifying access (no 'const')
void square_array(int array[], int n) {
for (int i = 0; i < n; i++) {
array[i] = array[i] * array[i];
}
}
int main(void) {
int array[5] = {1, 2, 3, 4, 5};
int sum = sum_of_array(array, 5); // 'array' decays to &array[0]
printf("Sum = %d\n", sum);
square_array(array, 5); // modifies the original array
for (int i = 0; i < 5; i++) {
printf("array[%d] = %d\n", i, array[i]);
}
sum = sum_of_array(array, 5);
printf("New sum = %d\n", sum);
return 0;
}
Key points
- Inside
sum_of_arrayandsquare_array, the parameterarrayis actually a pointer (int *array). - Therefore,
sizeof arrayinside the function would give the pointer size (e.g., 8 on 64‑bit), not the number of elements. - Use
constto make read‑only intent explicit and enforced by the compiler.
Sample output
Sum = 15
array[0] = 1
array[1] = 4
array[2] = 9
array[3] = 16
array[4] = 25
New sum = 55
(Optional) Multi‑dimensional arrays
For int m[R][C];, the array decays one level: m decays to int (*)[C] (pointer to an array of C ints). The rightmost dimension must be known at the call site to index correctly.
#include <stdio.h>
void zero2d(int (*mat)[4], int rows) { // pointer to array of 4 ints
for (int r = 0; r < rows; r++) {
for (int c = 0; c < 4; c++) {
mat[r][c] = 0;
}
}
}
int main(void) {
int m[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} };
zero2d(m, 3); // 'm' decays to pointer to row (int (*)[4])
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 4; c++) {
printf("%d ", m[r][c]);
}
printf("\n");
}
return 0;
}
Common pitfalls
sizeoftrap in callees:
Inside a function parameter declared asint a[](reallyint *a),sizeof ais pointer size, not the array length. Compute lengths in the caller:#define LEN(x) (sizeof(x)/sizeof((x)[0]))- Confusing
avs&a:
a(in expressions) → pointer to first element (T*).
&a→ pointer to the entire array (T (*)[N]). - Pointer arithmetic off‑by‑one:
End pointer isa + N. Valid indices are0..N-1; never dereferencea + N. - Const correctness:
Useconst T *parameters for read‑only functions to prevent accidental modification.
Summary
- An array is a contiguous block of elements with a fixed size; a pointer is a variable holding an address.
- In most expressions (including function calls), an array name decays to a pointer to its first element.
- Because of decay, functions that take “arrays” actually receive pointers—so also pass the length (or otherwise provide it).
sizeof aand&aare the two primary places you’ll see no decay and different types/values.