Pointers Deep Dive
Prerequisites: Level 1 — Beginner
Pointer arithmetic moves by the pointee's size, not by raw
bytes — p + 1 on an int * advances by sizeof(int) bytes, so it
correctly lands on the next int, whatever that type's size
happens to be.
int nums[4] = {10, 20, 30, 40};
int *p = nums;
printf("%d\n", *(p + 2)); // 30 — the third element
for (int *cur = nums; cur < nums + 4; cur++) {
printf("%d\n", *cur);
}
A pointer to a pointer (int **) holds the address of another
pointer — common when a function needs to modify a pointer itself
(not just the value it points to), such as reallocating memory a
caller's pointer variable should then reflect.
void allocate(int **p) {
*p = malloc(sizeof(int));
**p = 42;
}
int main(void) {
int *value;
allocate(&value);
printf("%d\n", *value); // 42
free(value);
return 0;
}
Common mistakes
- Doing pointer arithmetic past the end of an allocated block — even one element past the end is undefined behavior, whether or not it happens to "work" on a given run.