Arrays and Pointers
Arrays and pointers: the connection
Arrays and pointers are two of the most important — and most confusing — topics in C, largely because they are so closely linked. Once you see exactly how they connect, a lot of C suddenly makes sense: array indexing, passing arrays to functions, and strings all rely on this relationship.
The core fact is simple: the name of an array behaves like a pointer to its first element. If you understand that one sentence, the rest of this lesson is just seeing it in action. (If pointers are new to you, read pointers in C first.)
Why an array name is an address
When you write an array name by itself, C gives you the address of its first element. So a and &a[0] are the same address.
#include <stdio.h>
int main() {
int a[] = {10, 20, 30};
printf("a = %p\n", a);
printf("&a[0] = %p\n", &a[0]); // same address
printf("First value = %d\n", *a); // dereference a
return 0;
}a = 0x7ffee4a2c0
&a[0] = 0x7ffee4a2c0
First value = 10
Because a is the address of the first element, dereferencing it with *a gives 10 — the first value.
Pointer arithmetic on arrays
Here is the clever part. When you add 1 to a pointer, C does not move by 1 byte — it moves by one element. So for an int array, a + 1 jumps ahead by the size of one int and lands on the next element.
#include <stdio.h>
int main() {
int a[] = {10, 20, 30};
int *p = a; // p points to a[0]
printf("%d\n", *p); // 10 (a[0])
printf("%d\n", *(p + 1)); // 20 (a[1])
printf("%d\n", *(a + 2)); // 30 (a[2])
return 0;
}10
20
30
Notice we used both p and a with + — they work the same because both are addresses of the first element.
a[i] is the same as *(a+i)
This is one of the most important identities in C. The square-bracket notation you already know is just shorthand:
| You write | C treats it as |
|---|---|
a[0] | *(a + 0) |
a[1] | *(a + 1) |
a[i] | *(a + i) |
Because a[i] means *(a+i), and addition is commutative, i[a] also works and gives the same value! It looks strange but it is valid C.
Looping through an array with a pointer
You can walk through an entire array by moving a pointer forward one element at a time.
#include <stdio.h>
int main() {
int a[] = {10, 20, 30, 40, 50};
int n = 5;
int *p = a;
for (int i = 0; i < n; i++) {
printf("%d ", *p); // read current element
p++; // move to next element
}
return 0;
}10 20 30 40 50
Each p++ advances the pointer by one int, so it visits every element in order. This is exactly what happens behind the scenes when you use a[i] in a loop.
But an array is NOT a pointer
This is where many students get caught. Even though an array name acts like a pointer in expressions, they are genuinely different things. Two proofs:
#include <stdio.h>
int main() {
int a[] = {10, 20, 30};
int *p = a;
printf("sizeof(a) = %lu\n", sizeof(a)); // 12 (3 ints)
printf("sizeof(p) = %lu\n", sizeof(p)); // 8 (just a pointer)
// a = p; // ERROR: cannot reassign an array name
p = a + 1; // OK: a pointer can be reassigned
printf("Now p points to %d\n", *p); // 20
return 0;
}sizeof(a) = 12
sizeof(p) = 8
Now p points to 20
An array is a fixed block of memory — you cannot make its name point elsewhere. A pointer is a variable you can reassign. The array name only decays to a pointer in expressions.
Common mistakes
- Thinking
p + 1moves by one byte — it moves by one element. - Trying to reassign an array name (
a = something) — not allowed. - Expecting
sizeofon a pointer to give the array size — it gives the pointer size. - Reading past the last element with pointer arithmetic — that is out-of-bounds and unsafe.
Take an array of 5 integers and print them twice: once using a[i] and once using *(a+i). Confirm both loops give identical output — proving the two notations are the same.
Summary
- An array name gives the address of its first element, so it acts like a pointer.
- Pointer arithmetic moves in element-sized steps, so
a+1is the next element. a[i]is defined as*(a+i)— the same thing.- You can loop an array by advancing a pointer with
p++. - Still, an array is not a pointer:
sizeofdiffers and an array name cannot be reassigned.
Frequently Asked Questions
Is an array the same as a pointer in C?
Why does a[i] work the same as *(a+i)?
a[i] as exactly *(a + i). The array name gives the starting address, adding i moves forward by i elements, and * reads the value there. Both notations compile to the same thing.What is pointer arithmetic in the context of arrays?
p + 1 points to the next element, not the next byte. This is what makes walking through an array with a pointer possible.Why can I not assign to an array name like a = p?
Does sizeof give the same result for an array and a pointer?
sizeof(array) gives the total size of all elements, while sizeof(pointer) gives only the size of the pointer itself (typically 8 bytes). This proves that an array and a pointer are stored differently.