A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
The subscript operator arr[i] is defined as *(arr + i). Not approximately. Not as an optimization. By the language definition. The compiler translates every array subscript into pointer arithmetic. This means arr[i] and i[arr] are both valid and both mean the same thing. It also means that understanding pointer arithmetic is not optional. It is the actual mechanism underneath the syntax you use every day.
#include <stdio.h>int main(void) {int arr[] = {10, 20, 30, 40, 50};int *ptr = arr;printf("Subscript notation:\n");for (int i = 0; i < 5; i++) {printf(" arr[%d] = %d\n", i, arr[i]);}printf("\nPointer notation:\n");for (int i = 0; i < 5; i++) {printf(" *(ptr+%d) = %d\n", i, *(ptr + i));}printf("\nThe weird one:\n");printf(" 2[arr] = %d\n", 2[arr]);return 0;}
2[arr] compiles and prints 30. It is *(2 + arr), which is *(arr + 2), which is arr[2]. Addition is commutative. The syntax is legal. You should never write it. But knowing why it works proves you understand the underlying mechanism.
ptr + 1 does not add 1 byte. It adds sizeof(*ptr) bytes. For an int pointer on a system where int is 4 bytes, ptr + 1 advances 4 bytes. For a double pointer, it advances 8. This is why pointer arithmetic on void pointers is a GNU extension, not standard C: void has no size, so the compiler cannot scale the offset.
#include <stdio.h>int main(void) {int arr[] = {100, 200, 300};int *p = arr;printf("p = %p\n", (void *)p);printf("p + 1 = %p (diff: %ld bytes)\n", (void *)(p + 1), (long)((char *)(p + 1) - (char *)p));printf("p + 2 = %p (diff: %ld bytes)\n", (void *)(p + 2), (long)((char *)(p + 2) - (char *)p));return 0;}
Each increment moves 4 bytes because the pointed-to type is int. The addresses differ by exactly sizeof(int). This scaling is automatic. You never multiply by the element size yourself. The compiler does it based on the pointer's declared type.
Pointer notation is not a curiosity. It is how the compiler implements arrays. It is how you traverse buffers, walk linked structures, and parse binary protocols. The subscript syntax is sugar. The pointer arithmetic is the reality. Next: const pointers vs pointers to const, a distinction that trips up every C learner and many C veterans.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.