5.1.9 · D1C Programming

Foundations — Pointer arithmetic — adding integers to pointers

1,693 words8 min readBack to topic

Before you can trust the parent note's rule — p + n moves n × sizeof(*p) bytes — you must own every symbol it fires at you. This page builds each one from nothing, in the order that lets the next make sense.


0. Memory is one long numbered street

Everything starts here. Your computer's memory is not a cloud of stuff — it is a single, straight line of tiny boxes, and every box has a number, counted from the left. That number is called an address.

Figure — Pointer arithmetic — adding integers to pointers

Why hexadecimal? Because addresses get huge, and hex is a compact shorthand programmers agreed on. 0x1000 is just the ordinary number 4096 — the notation 0x... only means "read the following as base-16." You never have to do the base-16 math by hand here; treat 0x1000, 0x1004, 0x1008 as "some box, four boxes later, eight boxes later."


1. Type T — what kind of thing lives in a box

The letter T is not real C — it's a placeholder the parent uses to mean "whatever type we happen to be talking about." When you see T, mentally swap in int or char.

Figure — Pointer arithmetic — adding integers to pointers

Why does the topic need T? Because the stride — how far +1 jumps — is decided entirely by T. Without a type, a pointer wouldn't know how wide its houses are, and +1 would be meaningless.


2. sizeof(T) — the width of one house

Why this tool and not just "4"? Because if the parent wrote p + 1 moves "4 bytes," that would be a lie on machines where int is 8 bytes wide. sizeof is the honest, portable way to say "one house-width," whatever that turns out to be. See sizeof operator for the full story.


3. Variables and & — pointing at a specific box

Why does the topic need &? Because to make a pointer you need an actual address to store in it, and & is how you obtain one. &a[0] in the parent ("the address of the first array element") is this operator at work.


4. Pointer p and the * in a declaration

Figure — Pointer arithmetic — adding integers to pointers

Two very different jobs share the star symbol *. This trips up everyone, so nail it now:


5. Arrays and [] — a row of same-type houses

Figure — Pointer arithmetic — adding integers to pointers

Why the topic needs arrays: pointer arithmetic exists so you can walk arrays. The parent's identity arr[i] ≡ *(arr + i) only makes sense once you see the array as a contiguous row. See Arrays decay to pointers — an array name used in arithmetic quietly becomes a pointer to its first element.


6. Dereference *p — read the value inside the house

Why the topic needs it: pointer arithmetic computes addresses, but you usually want the value at those addresses. *(p + 2) = "go two houses along, then read." Without *, arithmetic gives you a location and nothing to do with it. Precedence details (why *p + 1 ≠ *(p+1)) live in Dereference operator and precedence.


7. The + on a pointer — and why it's special

Now every ingredient is on the table, the parent's core symbol makes sense.

Why is + overridden for pointers rather than adding plain 1? Because C wants p + i to land on a[i], and a[i] lives i × sizeof(T) bytes along (Section 5). Plain integer addition would land you inside a house — a bug. So the language scales by the house-width automatically. That's the entire trick, and it's why "step by TYPE, not by BYTE."

Related definable operations you'll meet next door: pointer − pointer gives a count of elements (see Pointer subtraction and ptrdiff_t); going past a[N] is out of bounds (see Undefined behavior and bounds).


Prerequisite map

Memory as numbered bytes

Address = box number

Type T

sizeof T = house width

Variable = named box

Address-of and

Pointer holds an address

Array = contiguous row

Dereference star p

Pointer plus integer


Equipment checklist

You are ready for the parent topic once you can answer each of these without peeking.

What is an address, in the street picture?
The position-number of a byte-box, counted from the start of memory; often written in hex like 0x1000.
What does sizeof(int) report, and why isn't it just always 4?
The number of bytes one int occupies (often 4, but machine-dependent) — C measures widths this way so code stays portable.
What does &x give you?
The address (house-number) of the variable x.
What is stored inside a pointer?
An address, plus a type that remembers the width sizeof(*p) of the thing pointed at.
In int *p; versus *p, what do the two * mean?
In the declaration * says "p is a pointer"; in the expression *p it dereferences — reads the value at that address.
Why do array elements land on neat boundaries for pointer math?
Arrays are contiguous, so a[i] sits exactly i × sizeof(T) bytes from the start.
What does *(p + 2) do, step by step?
Move p forward 2 × sizeof(*p) bytes to the third element, then read the value there.
Why does *p + 1 differ from *(p + 1)?
* binds tighter than +: *p + 1 reads then adds 1; *(p+1) steps to the next element then reads.