Pointer Basics
A pointer is a variable that holds an address — learn &, *, and NULL
Quick check before you start: Can you explain the difference between a variable’s value and its memory address? If not, read on. If you can, skip to Declaring Pointers.
Practice this topic: Pointers skill drill
After this lesson, you will be able to:
- Explain the difference between a variable’s value and its memory address
- Declare pointer variables and assign them using the
&(address-of) operator - Dereference a pointer with
*to read and write the value at the pointed-to address - Distinguish between
*in a declaration (pointer-to) and*in an expression (dereference) - Use
NULLto represent a pointer that points to nothing
A Pointer Is a Variable That Holds an Address
In Java, when you write ArrayList<Integer> list = new ArrayList<>(), the variable list holds a reference – an invisible pointer to the object on the heap. You never see the address, never manipulate it directly.
C rips that curtain away. In C, you can see the address of any variable, store it in another variable, and follow it to read or modify the original. This is what a pointer is – a variable that holds a memory address.
Every Variable Has an Address
Every variable lives somewhere in memory. The & operator gives you that address:
int x = 42;
printf("Value of x: %d\n", x);
printf("Address of x: %p\n", (void *)&x);
Value of x: 42
Address of x: 0x7ffd5e8a3c2c
That hex number is where x lives in RAM. It is a real location on your computer.
Declaring Pointers
A pointer variable stores an address. Declare it with *:
int *p; /* p is a pointer to an int */
double *q; /* q is a pointer to a double */
char *s; /* s is a pointer to a char */
Key Insight: Read pointer declarations right-to-left:
int *pmeans “p is a pointer to an int.” The*in the declaration means “pointer to.” This is different from the*used for dereferencing.
Making a Pointer Point to Something
Use & to get a variable’s address, then assign it to a pointer:
int x = 42;
int *p = &x; /* p now points to x */
In memory:
Variable Address Value
+------+
| x | 0x1000 -> [ 42 ]
+------+
+------+
| p | 0x1008 -> [0x1000] --> points to x
+------+
p does not contain 42. It contains the address where 42 lives.
Dereferencing: Following the Arrow
The * operator (dereference) follows the pointer to access the value it points to:
int x = 42;
int *p = &x;
printf("p holds address: %p\n", (void *)p); /* 0x1000 */
printf("*p follows it: %d\n", *p); /* 42 */
You can also write through a pointer:
*p = 99;
printf("x is now: %d\n", x); /* 99 */
Key Insight:
*pon the left side of=writes to the location p points to.*pon the right side reads from it. The pointer itself (p) holds the address; the dereferenced pointer (*p) accesses the value at that address.
The Two Faces of *
This trips everyone up: * means two different things depending on context:
| Context | Meaning | Example |
|---|---|---|
| Declaration | “pointer to” | int *p; – p is a pointer to int |
| Expression | “dereference” | *p = 42; – write 42 to where p points |
From Java: Java references are invisible pointers. When you write
obj.method(), Java automatically dereferences the reference to find the object. In C, you do this explicitly with*p. The mechanism is the same – C just makes you do it by hand.
NULL Pointers
A pointer that points to nothing should be set to NULL:
int *p = NULL; /* Points to nothing */
Dereferencing a NULL pointer crashes your program (segmentation fault). Always check:
if (p != NULL)
{
printf("Value: %d\n", *p);
}
Common Pitfall: An uninitialized pointer contains a garbage address – it points to some random location in memory. Dereferencing it might crash, or worse, silently corrupt data. Always initialize pointers to either a valid address or
NULL.
Memory Diagrams Are Your Best Tool
Draw these for every pointer problem:
int a = 10; int b = 20; int *p = &a;
+---+ +---+ +-----+
| a | = 10 | b | = 20 | p | --> a
+---+ +---+ +-----+
*p = 30; /* a is now 30 */
p = &b; /* p now points to b */
*p = 40; /* b is now 40 */
Final: a = 30, b = 40
The Trick: When pointer code confuses you, draw boxes. One box per variable, arrows from pointers to what they point to. Trace each line of code by updating the diagram. This technique works for every pointer problem you will encounter.
x after line 4?int x = 10; // line 1int *p = &x; // line 2*p = *p + 5; // line 3x = *p + x; // line 4*p = *p + 5 writes 15 to x (since p points to x). On line 4, *p is 15 and x is also 15 (same memory), so x = 15 + 15 = 30. The key: *p and x refer to the same location, so changing one changes the other.
What Comes Next
You now understand the core mechanism: & gets an address, * follows it. That is the foundation for everything in Week 6.
Next lesson: pass-by-pointer. Remember the swap function that did not work with pass-by-value? With pointers, you can finally fix it. Pointers let functions modify their caller’s variables – the missing piece.