← Pointers and MemoryC PROGRAMMING 1.2.C

Pointer Arithmetic & Arrays

Array decay, scaling, indexing sugar, p++/++p, *p++ vs *++p vs (*p)++, pointer subtraction, out-of-bounds.

StatusCollected
NotesChapter test: 4/5

Ten pieces — this is where arrays and pointers turn out to be the same mechanism wearing different syntax, and where a handful of operators that look nearly identical (*p++, *++p, (*p)++) turn out to do genuinely different things.

Array decay

int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;             /* arr "decays" to a pointer to its first element */

printf("%d\n", *p);       /* 10 */
printf("%d\n", *(p+2));   /* 30 — p+2 skips two ints, not two bytes */
printf("%d\n", p[2]);     /* 30 — arr[i] is really just *(arr + i) */

arr[i] and *(arr + i) compile to the exact same thing. That's the whole reason array indexing works through a plain pointer at all — it's syntactic sugar over pointer arithmetic.

Scaling

p + n advances by n elements, not n bytes — the compiler scales by sizeof(*p) automatically. p + 1 on an int * moves 4 bytes; on a double * it moves 8.

p++ vs ++p vs p++ vs ++p vs (*p)++

int arr[3] = {1, 2, 3};
int *p = arr;

int a = *p++;    /* a = 1, then p advances to arr[1] — postfix ++ binds to p, not *p */
int b = *++p;    /* p advances to arr[2] first, then b = 3 */
int c = (*p)++;  /* c = 3 (old value), then arr[2] becomes 4 */

++ binds to the pointer itself unless parentheses say otherwise — *p++ increments the pointer after dereferencing the old address, *++p increments the pointer first, and (*p)++ is the odd one out that actually changes the pointed-to value instead of the pointer.

Pointer subtraction and bounds

Subtracting two pointers into the same array gives the number of elements between them, not bytes — p2 - p1 on two int * values is already scaled down. Going past the end of an array with pointer arithmetic — even just computing the out-of-bounds address without dereferencing it — is undefined behavior, not just risky.

Notes from readers

Comments — via GitHub