Pointers & Arrays
Moving through memoryArrays and pointers are close relatives in C. The name of an array turns into the address of its first element, and adding to a pointer moves it by whole elements. In the lab below you watch the addresses jump by 1, 4 or 8 bytes, sum an array with a moving pointer, and measure a string by walking to its '\0'.
- aacts like &a[0]
- p + 1the next ELEMENT, not the next byte
- a[i]is *(a + i)
Ready
Keyboard: ← → step · Space play / pause · R reset · Esc exit classroom mode
The ideas behind the lab
Exactly what you watched happen, in plain steps.
An array name becomes a pointer
When you use an array name in an expression, C turns it into a pointer to its first element: a means &a[0]. Adding an integer to a pointer moves it by whole elements — p + 1 is the next int, 4 bytes further — so *(p + i) is element i. That is exactly what a[i] means: a[i] is defined as *(a + i). Pointers into the same array can also be compared and subtracted.
int a[5] = {10, 20, 30, 40, 50};
int *p = a; // p = &a[0]
*(p + 2) // 30 — same as a[2] and p[2]
p++; // p → a[1] (address + 4 bytes)
p - a // 1 element
for (p = a; p < a + 5; p++)
printf("%d ", *p);
| Expression | Same as | Value / address |
|---|---|---|
| a | &a[0] | 0x1000 |
| a + 3 | &a[3] | 0x100c (3 × 4 bytes on) |
| *(a + 3) | a[3] | the 4th element |
| p[i] | *(p + i) | element i counted from p |
| p++ | p = p + 1 | next element (+4 bytes for int, +1 for char, +8 for double) |
| q - p | — | number of elements between them |
Pointer arithmetic
- p + n moves n elements: n × sizeof(*p) bytes.
- p++ and p-- step one element forward or back.
- q - p (same array) gives the number of elements between them.
- p < q compares positions in the same array.
- You may point one past the last element, but never dereference it.
Arrays vs pointers
- a[i] and *(a + i) are the same thing; so are p[i] and *(p + i).
- An array name cannot be changed: a++ is an error; p++ is fine.
- sizeof a gives the whole array; sizeof p gives 8 (just the pointer).
- Passing an array to a function passes &a[0] — the parameter is really a pointer.
- So int f(int a[]) and int f(int *a) mean the same.
Pointers and strings
- A char * can walk a string: while (*p) p++; stops at '\0'.
- p - s is then the length.
- char s[] = "hi"; is an array you may change.
- char *t = "hi"; points to a string literal — do not change it (const char * is better).
- Two pointers moving towards each other can reverse a string in place.
Reverse a string with two pointers, print part of an array
Every line, explained.
#include <stdio.h>
#include <string.h>
void reverse(char *s)
{
char *left = s;
The first character.
char *right = s + strlen(s) - 1;
The last character (before '\0').
while (left < right) {
Until they meet.
char t = *left;
*left++ = *right;
Store, then move left forward.
*right-- = t;
Store, then move right back.
}
}
void printAll(const int *p, int n)
Receives any part of an int array.
{
for (int i = 0; i < n; i++)
printf("%d ", *(p + i));
printf("\n");
}
int main(void)
{
char word[] = "stressed";
reverse(word);
printf("%s\n", word);
Prints desserts
int a[] = {5, 10, 15};
printAll(a, 3);
Prints 5 10 15
printAll(a + 1, 2);
Starts at a[1]: prints 10 15
return 0;
}
Spot the bug
Mistakes almost every beginner makes — and how to fix them.
Thinking p + 1 is the next byte
int *p = a; int *q = p + 4; // "4 bytes on"?
int *p = a; int *q = p + 1; // the next int (4 bytes on)
Pointer arithmetic counts elements; C multiplies by the element size for you.
Changing the array name
int a[5]; a++; // error
int *p = a; p++;
An array name is not a variable; it always means the start of the array.
Dereferencing one past the end
for (p = a; p <= a + 5; p++) sum += *p;
for (p = a; p < a + 5; p++) sum += *p;
a + 5 may be used for comparing, but there is no element there to read.
Changing a string literal
char *s = "hello"; s[0] = 'H'; // crash
char s[] = "hello"; s[0] = 'H';
A pointer to a literal points into read-only memory. An array gets its own copy.
sizeof on a pointer
int *p = a; int n = sizeof p / sizeof *p; // 2, not 5
int n = sizeof a / sizeof a[0]; // only on the array itself
sizeof p is the size of the pointer (8), not of the array it points into.
Check your understanding
Answer each question — you will see the explanation straight away.
int a[] = {4, 8, 12}; int *p = a; — what is *(p + 1)?
p + 1 points to a[1].
If an int pointer p holds 0x1000, what does p + 2 hold (4-byte int)?
2 elements × 4 bytes = 8 bytes on.
Which expression is the same as a[3]?
a[i] is defined as *(a + i).
char s[] = "code"; char *p = s; while (*p) p++; — what is p - s?
p stops at '\0', 4 characters on.
int a[5]; — which statement is an error?
The array name cannot be changed.
Pointers & Arrays quiz
Test yourself: 10 questions, 70% to pass. Create a free account to take the quiz, save your progress and work towards the certificate.