Pointer arithmetic
Add and subtract integers from pointers to navigate memory — understanding how the compiler scales pointer arithmetic by the element type size.
- Add an integer to a pointer and explain the resulting address
- Subtract two pointers of the same type to find the distance between them
- Explain that pointer arithmetic is scaled by sizeof the pointed-to type
- Iterate over an array using a pointer rather than an index
Pointers are not just addresses — they support arithmetic. You can add or subtract integers to move a pointer forward or backward through memory. The critical insight: pointer arithmetic is scaled by the size of the type being pointed to. Adding 1 to an int * moves it forward by sizeof(int) bytes (typically 4), not by 1 byte.
Adding to a pointer
#include <stdio.h>
int main(void) {
int arr[] = {10, 20, 30, 40, 50};
int *p = arr; /* p points to arr[0] */
printf("*p = %d\n", *p); /* 10 */
printf("*(p + 1) = %d\n", *(p + 1)); /* 20 */
printf("*(p + 2) = %d\n", *(p + 2)); /* 30 */
printf("*(p + 4) = %d\n", *(p + 4)); /* 50 */
return 0;
}p + 1 does not add 1 to the address. It adds 1 * sizeof(int) — 4 bytes — moving to the next int in the array. This is why pointer arithmetic works correctly regardless of element size.
In memory:
address: 1000 1004 1008 1012 1016
value: 10 20 30 40 50
^p ^(p+2)Iterating with a pointer
The pointer approach to array iteration is equivalent to the index approach:
int arr[] = {10, 20, 30, 40, 50};
int n = 5;
/* Index-based */
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
/* Pointer-based */
for (int *p = arr; p < arr + n; p++) {
printf("%d ", *p);
}Both print 10 20 30 40 50. The pointer version uses p++ to advance by one element and checks p < arr + n (one past the last element) as the stop condition.
Subtracting two pointers
Subtracting two pointers of the same type gives the number of elements between them:
int arr[] = {10, 20, 30, 40, 50};
int *start = arr;
int *end = arr + 5;
ptrdiff_t count = end - start; /* 5, not 20 */
printf("Elements between: %td\n", count);The result type is ptrdiff_t (from <stddef.h>). Use %td to print it. As with addition, the subtraction is scaled by element size — the result is the number of elements, not bytes.
Finding a character in a string:
#include <string.h>
const char *str = "hello";
const char *pos = strchr(str, 'l');
if (pos) {
ptrdiff_t index = pos - str;
printf("'l' is at index %td\n", index); /* 2 */
}Pointer comparison
You can compare pointers with <, >, <=, >=, ==, and != when they point into the same array (or one past the end). This is how the while pointer loop works:
char str[] = "Hello";
char *p = str;
while (*p != '\0') {
printf("%c", *p);
p++;
}p++ advances to the next character. *p != '\0' checks whether we have reached the null terminator.
The equivalence of array indexing and pointer arithmetic
In C, arr[i] is exactly equivalent to *(arr + i). The compiler translates array subscripts into pointer arithmetic. This is not a metaphor — the language specification defines it this way.
int arr[] = {10, 20, 30};
printf("%d\n", arr[2]); /* 30 */
printf("%d\n", *(arr + 2)); /* 30 -- identical */
printf("%d\n", 2[arr]); /* 30 -- obscure but valid: 2 + arr */The last line (2[arr]) is valid because a[b] and b[a] are the same: *(a + b) vs *(b + a). Mention this only to understand the underlying model — do not write it in real code.
Only do pointer arithmetic within the bounds of an array. Accessing past the end (more than one past the last element) is undefined behaviour. Comparing pointers from different arrays is also undefined behaviour. Pointer arithmetic is only safe when you know the bounds of the memory region you are navigating.
Where to go next
Next: pointers and arrays — the relationship between array names and pointers, how arrays decay into pointers, and why understanding this decay is essential for passing arrays to functions.
What is a pointer?
Learn what pointers are in C — memory addresses, the address-of and dereference operators, and why pointers are the core of C's power.
Pointers and arrays
Understand the deep relationship between pointers and arrays in C — how array names decay to pointers, why sizeof behaves differently, and how to write generic array functions.