Pointers Part 1: Addresses, Declaration, Dereferencing
This is the first of several pointer chapters. It establishes the three operations that define pointers — taking an address, declaring a pointer, and dereferencing — and builds the mental model that later chapters extend.
Why This Matters
Pointers are the most important feature of C and the one most programmers from managed languages get wrong. A pointer is not "a number." It is a typed value that designates an object. Everything about memory management, arrays, strings, structs, and systems programming rests on this model.
Prerequisites
c.core.5— pointer types andvoid.c.core.7— scope, storage duration, lifetime.
Core Concept
A pointer designates an object
A pointer is a value that, when valid, points to (designates) an object. The pointer has a type, T *, where T is the type of the object it points to.
Three fundamental operations:
1. Address-of: &obj yields a pointer to obj. 2. Declaration: T *p; declares p as a pointer to T. 3. Dereference: *p yields the object p points to (an lvalue).
These three operations are inverses in the well-defined case:
int x = 5;
int *p = &x; /* p points to x */
*p = 10; /* *p is x; now x is 10 */
The pointer model, precisely
A pointer has three components (developed fully in c.obj.provenance):
- an address (where the object is);
- a type (what the object is, which controls access size and arithmetic);
- provenance (which object it points into — this is what makes pointer
arithmetic and aliasing well-defined).
Syntax
Declaring pointers
int *p; /* pointer to int */
char *s; /* pointer to char */
double *d; /* pointer to double */
The * binds to the declarator. int *p, q; declares p as int * and q as int.
Address-of and dereference
int x = 5;
int *p = &x; /* &x is the address of x */
*p = 10; /* *p designates x */
Null pointer
int *p = NULL; /* NULL from <stddef.h> or other standard headers */
NULL is a null pointer constant. A null pointer does not point to any object. Dereferencing it is undefined behavior.
Examples
Minimal example
int x = 42;
int *p = &x;
printf("%d\n", *p); /* 42 */
Normal example: swapping via pointers
#include <stdio.h>
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int main(void)
{
int x = 1, y = 2;
swap(&x, &y);
printf("%d %d\n", x, y);
return 0;
}
Expected output: 2 1.
Realistic example: reading through a pointer to a struct
struct Config { int retries; int timeout; };
void apply_defaults(struct Config *c)
{
if (c->retries == 0) c->retries = 3; /* -> is (*c). */
if (c->timeout == 0) c->timeout = 30;
}
Dangerous example: dereferencing NULL
int *p = NULL;
int x = *p; /* UNDEFINED BEHAVIOR: null dereference */
On most hosted systems this crashes with a segmentation fault, but the standard guarantees nothing.
How It Works
&x produces the address of the object x. Storing it in p gives p a value that designates x. *p follows the pointer to read or write x. At the machine level, p is (usually) an address in a register; the dereference generates a load or store instruction of the pointed-to type's size.
Variations
Pointer to const, const pointer (later)
const interacts with pointers in four ways; that is covered in c.core.25. For now, know that const int *p is a pointer to a const int, while int *const p is a const pointer to a non-const int.
Pointers to pointers (later)
int **pp is a pointer to a pointer to int. Covered in c.core.24.
Function pointers (later)
int (*fp)(int) is a pointer to a function taking int and returning int. Covered in c.core.32.
Common Mistakes
- Declaring
int* p, q;and expecting both to be pointers. - Dereferencing an uninitialized (wild) pointer.
- Dereferencing a NULL pointer.
- Confusing the pointer with the pointed-to object.
- Forgetting that
*p = xwrites to the object, whilep = &xchanges the
pointer.
Undefined Behavior
- Dereferencing a null pointer.
VERIFIED - Dereferencing a wild (indeterminate) pointer.
VERIFIED - Dereferencing a dangling pointer (to an object whose lifetime ended).
VERIFIED
- Dereferencing a misaligned pointer.
VERIFIED - Dereferencing a pointer that does not point to a valid object (e.g., a made-up
address). VERIFIED
Portability
- The representation of a pointer is implementation-defined; do not assume it
equals int or long.
NULLis portable;0used as a pointer is also a null pointer constant.- Converting between pointer types has strict rules (
c.ptr.void,
c.obj.aliasing).
Under the Hood
A pointer is typically a machine word holding a virtual address. Dereferencing compiles to a load/store of the pointed-to type's width. The type is *not* stored at run time; the compiler uses it at compile time to pick the instruction and the access width.
Practical Usage
- Use pointers for output parameters (functions that modify caller data).
- Use pointers to avoid copying large structs.
- Use pointers to build dynamic data structures and to own heap allocations.
Exercises
1. Write a function increment(int *p) and call it; verify the caller's value changes. 2. Write a program that prints the address and the pointed-to value of an int, and confirm the address matches &x. 3. Deliberately dereference NULL and observe the crash (run in a safe, contained way). Explain why the behavior is not guaranteed. 4. Explain the difference between int *p = &x; and *p = 5;.
Deep Challenge
Write a function that takes a pointer to a pointer and swaps two pointers (similar to swap, but swapping the pointer values themselves). Explain each level of indirection and why a single * would be insufficient.
Related Concepts
c.core.20— pointer arithmetic.c.core.24— pointer-to-pointer and void*.c.core.25— const/volatile/restrict.c.obj.provenance— pointer provenance.
References
- ISO/IEC 9899:2018 §6.2.5 (pointer types), §6.5.3.2 (address and
indirection), §6.3.2.3 (pointer conversions).
Verification
- Address-of, declaration, and dereference semantics are standard.
VERIFIED - Null dereference is UB.
VERIFIED int *p, q;declares onlypas pointer.VERIFIED- No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] Address-of operator
- [ ] Pointer declaration
- [ ] Dereference operator
- [ ] Null pointers
- [ ] Pointer declarator binding
- [ ] Swapping via pointers
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.ptr.basics | 0 | 6 |