C Pointers
The Sticky Note Analogy
Imagine you have a box in a warehouse at shelf B7. A pointer is a sticky note that says "B7" β it doesn't contain the item, it just tells you where to find it.
In C, every variable lives at a specific memory address. A pointer is a variable that stores that address. Instead of holding a number or a character, it holds the location of another variable.
Two Key Operators
&(address-of) β "What's the address of this box?" Give me the sticky note.*(dereference) β "Go to this address and get what's inside." Follow the sticky note to the box.
These two operators are inverses. *(&x) gets the address of x, then immediately follows it back β so it's just x again.
Basic Pointer Usage
Pointer Types Matter
A pointer has a type β int*, char*, float*. The type tells the compiler how many bytes to read when you dereference. An int* reads 4 bytes, a char* reads 1 byte, a double* reads 8 bytes.
You can think of it this way: the address tells you which locker to go to, and the type tells you how many lockers to open to get the full value.
NULL β The Pointer to Nowhere
NULL is a special value meaning "this pointer doesn't point to anything." It's used to signal that a pointer is intentionally empty. You should always initialize pointers to NULL if you don't have an address for them yet.
Printing Addresses of Different Types
Pointers Unlock Pass-by-Reference
Remember how C is pass-by-value? Functions get a copy of arguments, so they can't change the originals. But if you pass a pointer to the variable, the function gets a copy of the address β and it can use that address to reach into the caller's memory and modify the original.
The classic example is a swap function. Without pointers, it's impossible. With pointers, it's elegant.
Swap β Without and With Pointers
NULL β and check for NULL before dereferencing. An uninitialized pointer holds a random garbage address, which is even worse than NULL because it might silently corrupt data instead of crashing.Common Pointer Mistakes
Pointers are powerful but unforgiving. Here are the classic traps:
- Forgetting
&β passing the value instead of the address to a function expecting a pointer - Dangling pointers β pointing to memory that's been freed or a local variable that went out of scope
- Uninitialized pointers β using a pointer before assigning it an address
- Type mismatch β assigning an
int*to achar*without understanding the consequences
The good news: these mistakes get easier to spot with practice. The compiler warnings are your friend β never ignore them.