Introduction
Arrays and pointers are closely tied in C. Used as a value, an array's name turns into the address of its first element.
Once you see that an array name is really an address, a great deal of C makes sense: why arrays are not copied into functions, why strings need no &, and why sizeof can give a surprising answer.
How it works
Walking with a pointer
#include <stdio.h>
int main(void) {
int nums[4] = {10, 20, 30, 40};
int *p = nums;
printf("%d %d\n", *p, *(p + 2));
p++;
p++;
printf("%d %d\n", *p, p[1]);
int sum = 0;
for (int *q = nums; q < nums + 4; q++) sum += *q;
printf("sum %d\n", sum);
return 0;
}int *p = nums; points p at nums[0]. Watch the arrow: p++ does not add 1 byte, it moves to the next int (4 bytes further), so the arrow steps along the cells. *(p + 2) and p[2] mean exactly the same thing.
Syntax
int a[4] = {1, 2, 3, 4};
int *p = a;
*(p + 2); // same as a[2]
p++; // now points at a[1]
int sum(const int *a, int n);
Example
When you pass an array, C passes the address of its first element, not a copy. The function can therefore change the caller's array, and it needs the length as a separate parameter:
#include <stdio.h>
void double_all(int a[], int n) {
for (int i = 0; i < n; i++) {
a[i] = a[i] * 2;
}
}
int main(void) {
int scores[3] = {5, 8, 13};
double_all(scores, 3);
printf("%d %d %d\n", scores[0], scores[1], scores[2]);
return 0;
}Inside double_all, a is an arrow into main's array. Changing a[i] changes scores itself.
Line by line
double_alltakes the array's address, and its length.- The loop runs over indexes 0 to
n - 1. a[i] = a[i] * 2changes the caller's array, becauseapoints at it.mainpassesscores, and its length, 3.printfshows the doubled values.
Expected result
10 16 26
In the real world
Passing an address instead of copying is why C can hand a million-element array to a function instantly. The standard functions memcpy and qsort work this way, with a pointer and a length.
Common mistakes
sizeofon an array parameter gives the size of a pointer (8), not of the array. Pass the length.- Moving a pointer past the end of the array and then reading through it.
- Forgetting that a function can change an array you pass to it.
Best practices
- Pass the length as a separate parameter.
- Mark a pointer parameter
constif the function only reads through it. - Prefer indexes when they are clearer, since
a[i]and*(a + i)mean the same thing.
Summary
An array name acts as the address of its first element. Pointer arithmetic moves by whole elements. Functions receive that address, so they can change the array and need its length passed in.
Quick check
Key takeaways
- p + 1 moves by one element, not one byte.
- A function given an array can change it.
- Always pass the length along with the array.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.