
Pointers Aren’t **Magic: How To Learn &Kung-fu
If you’ve ever cracked open a C tutorial and hit the chapter on pointers, you probably felt the same thing I did:
confusion, dread, and maybe a little bit of rage.
But here’s the thing — pointers aren’t magic. They’re just variables that store addresses instead of values. Once you get that, everything else starts to click.
This post walks through some basics from my Pointer Dojo — a little training ground I built to sharpen my understanding of memory in C.
What Even Is a Pointer?
Normally, a variable holds data:
int x = 42;
Here, the variable x stores the value 42. A pointer, on the other hand, holds the address of another variable:
int x = 42;
int *ptr = &x; // "ptr points to x"
&x means “the address of x” in C. So, *ptr doesn’t hold 42, it holds the address of X in memory, which would be something like 0x7ffeefbff5c. That memory address will be x’s and at that address, will be the number 42.
That’s why they’re called pointers, it’s basically C telling the computer “this thing is found in that house” as opposed to directly assigning it that thing.
Dereferencing: The Secret Sauce
Once you’ve got that sweet, sweet pointer, you can dereference it by using the * operator to get the value at the address it points to.
printf("%d\n", *ptr); // prints 42
All the above code is doing is telling the computer “Hey, go to the address inside ptr, and print out the value you find there.
Cool, Why Do I Need To Care?
You might be thinking: “Okay, but why not just use x directly?” like every other language?
Pointers matter because they let you:
- Pass data around efficiently (especially large structs).
- Work with dynamic memory (via malloc / free).
- Build flexible data structures like linked lists, trees, and hashmaps.
Without pointers, C wouldn’t be C and you wouldn’t be able to talk trash to people who are terrified of memory management.
Enter The Dojo, Daniel-San
Here’s an example straight from the Pointer Dojo I wrote to drill these concepts into my head:
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
swap(&x, &y);
printf("x = %d, y = %d\n", x, y); // x = 10, y = 5
}
The swap function here has the job of swapping the values we pass into it, which are two integers a and b.
If we just said a = b, we wouldn’t be swapping the values, we’d just be assigning them locally within the function and when we run the program, we’re just going to turn x into 10.
Inside swap, we set up a variable called temp to hold the value of a for us. We do this by pointing it to the address of whatever the first integer is that gets passed into the function.
We then tell C to change the value of whatever is at the address of the second integer that gets passed into the function to whatever is at the address of the first integer passed into the function.
So, whatever b was, now that value matches a.
Finally, we assign whatever the value of temp is (which we already know is a) to the address of the second integer that gets passed into the function.
Effectively we have now swapped the two values, and can call swap on two numbers we assign in the function main.
Wrapping Up With A Mental Model
Pointers are like learning to drive stick shift: confusing at first, but once it clicks, you feel more connected to the machine. And decidedly more European for the experience.
Here’s the mental model I used to understand how memory works in C and get this concept down for good.
-
A VARIABLE is like a house, so int hp = 50, is a house called HP with the number 50 in it.
-
A POINTER is like a map TO that house, so if we say int *ptr = &hp, then the value of ptr is whatever the address of HP is.
-
So &hp is saying “give me the address of HP”.
-
The * OPERATOR is telling the compiler to “follow the map” to the house and see what’s in it.
-
If we type *ptr, and ptr points to hp, then *ptr would be 50.
-
You can also change what’s in the house by typing *ptr = 100, and then hp would be 100.
-
ARRAYS are like a neighorhood with multiple houses, so int party[4] is 4 houses in a row.
-
If I reference party[0], I’m referencing the first house in the neighborhood..
-
party[1] is the second house, and so on. Array names and pointers are roughly interchangeable.
-
& means “give me the address of this house”
-
- means “follow the map to the house and see what’s in it”
-
-> means “follow the map to the house, then go to this specific room”
-
Arrays “decay” into pointers when you pass them to functions.
If you want to practice, check out the Pointer Dojo — I’m using it as a lightweight way to drill memory concepts for security research, game dev, and the gnarly side of C programming.
And remember: pointers aren’t magic. They’re just addresses — and now you know how to use them.