Skip to content
AgileLogics
6 min read

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.