← Blog

25 September 2026

Pointers in C: Why They Actually Confuse Everyone (And How to Think About Them)

Pointers don't confuse people because the syntax is hard. They confuse people because everyone learns the syntax (* and &) before anyone explains what a pointer actually is. Fix that order, and the syntax stops being a mystery.

What a pointer actually is

A variable is a labeled box holding a value. int x = 5; creates a box named x, holding 5, at some address in memory — say, address 1000.

A pointer is just another box, except the value it holds is an address, not an ordinary number. int *p = &x; creates a box named p whose value is 1000 — the address of x. That's it. p doesn't "become" x; p stores where x lives.

  • &x means "give me the address of x" → 1000.
  • *p means "go to the address stored in p, and give me the value sitting there" → 5.

& and * are opposites of each other: one converts a variable into its address, the other converts an address back into the value at that address.

The example that makes it click: swapping two variables

Here's the classic C interview/viva question — write a function that swaps two integers:

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    swap(&x, &y);
    // x is now 10, y is now 5
}

Walk through what actually happens in memory. Say x lives at address 1000 and y at address 1004. The call swap(&x, &y) passes the addresses 1000 and 1004 into the function — so inside swap, a = 1000 and b = 1004.

  1. int temp = *a; — go to address 1000, read the value there (5), store it in temp.
  2. *a = *b; — go to address 1004, read the value there (10), and write it into address 1000. Now x (at 1000) holds 10.
  3. *b = temp; — write temp's value (5) into address 1004. Now y (at 1004) holds 5.

Because a and b point at x and y's actual memory — not copies of their values — the changes made inside swap are visible back in main after the function returns. This is also exactly why void swap(int a, int b) (without pointers) can never work: C passes arguments by value, so a and b would just be local copies of 5 and 10, and swapping those copies has no effect on x and y at all.

Pointer arithmetic doesn't move by "1"

The second big confusion: p + 1 does not mean "add 1 to the address." It means "move forward by one element of whatever type p points to."

int arr[3] = {10, 20, 30};
int *p = arr;      // p now holds the address of arr[0]
// p + 1 points to arr[1] — the address moves forward by sizeof(int), which is 4 bytes
// p + 2 points to arr[2] — 8 bytes forward

If p held address 1000, then p + 1 is 1004, not 1001 — because int is 4 bytes on most systems, and pointer arithmetic automatically scales by the size of the type being pointed to. A char * would move by 1 byte per +1; a double * would move by 8. This is also why arr[i] is really shorthand for *(arr + i) — the compiler is doing exactly this scaled-address math underneath the array syntax.

The bugs this mental model prevents

Once "a pointer stores an address, not a value" is solid, three classic bugs stop being mysterious:

  • Dereferencing an uninitialized pointer (int *p; *p = 5;) — p holds a garbage address (whatever leftover bits were in that memory), so you just wrote 5 into a random, possibly-protected memory location. Always initialize a pointer (to a real address, or to NULL) before dereferencing it.
  • Dereferencing NULL — NULL is a reserved address (usually 0) meaning "points to nothing." Dereferencing it crashes on purpose, so the bug is caught immediately instead of silently corrupting memory elsewhere.
  • Dangling pointers — after free(p), the address p holds is no longer yours to read or write, even though p itself still "remembers" that address. Using *p after free(p) reads or writes memory the program no longer owns.

For your viva

  • A pointer's value is an address; the thing at that address is a separate value, reached via *.
  • &variable → its address. *pointer → the value at that address.
  • Passing a pointer to a function lets the function modify the caller's original variable — passing the variable itself only gives the function a copy.
  • pointer + n advances by n × sizeof(type) bytes, not n bytes.

Sumantrak™ is an AI mentor built for Indian engineering, diploma, BCA and BSc CS/IT students — Programming, Data Structures, and the rest of your syllabus, explained like this. Free to start →