AnyCompiler

Pointers and Arrays

When an array is used in most expressions, it 'decays' into a pointer to its first element — that's why int *p = numbers works with no & needed. Once p points at the array's start, p + 1 doesn't mean 'add 1 to the address' — it means 'move forward by one int', with the compiler automatically scaling by sizeof(int).

#include <stdio.h>

int main() {
    int numbers[3] = {10, 20, 30};
    int *p = numbers;
    printf("%d %d %d\n", *p, *(p + 1), *(p + 2));
    printf("%d %d %d\n", p[0], p[1], p[2]);
    return 0;
}
Output
10 20 30
10 20 30

numbers[i] is literally defined as *(numbers + i) — square-bracket indexing is pointer arithmetic with friendlier syntax, not a separate language feature. This is why C arrays have no bounds checking: numbers[i] is just an address computation, and the compiler has no way to know if that address is still inside the array.

Next: strings — why C has no built-in string type, and what one actually is under the hood.

Practice exercise

Given int numbers[3] = {10, 20, 30} and int *p = numbers, print the second element using pointer arithmetic (*(p + 1)).