C Mastery / Pointers Part 1: Addresses, Declaration, Dereferencing
Part 1 — The Core Language

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

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):

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

pointer.

Undefined Behavior

VERIFIED

address). VERIFIED

Portability

equals int or long.

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

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.

References

indirection), §6.3.2.3 (pointer conversions).

Verification

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.ptr.basics06