5.1.9C Programming

Pointer arithmetic — adding integers to pointers

1,772 words8 min readdifficulty · medium4 backlinks

WHAT is pointer arithmetic?

The key idea: pointer arithmetic is scaled by the pointed-to type.

  • int *p;p + 1 moves by sizeof(int) (often 4) bytes.
  • char *c;c + 1 moves by sizeof(char) = 1 byte.
  • double *d;d + 1 moves by sizeof(double) (often 8) bytes.

WHY does it scale by the type? (Derivation from first principles)

Let's derive it. Suppose an array T arr[N] starts at byte address AA.

Each element occupies s=sizeof(T)s = \texttt{sizeof}(T) bytes laid back-to-back. So:

byteaddr(arr[i])=A+is\text{byteaddr}(\texttt{arr[i]}) = A + i\cdot s

Now we define the pointer p = arr (so p holds address AA). We demand that *(p + i) equal arr[i]. For that to be true, p + i must produce the byte address A+isA + i\cdot s. Therefore the rule for + on a pointer must be:

p+i    (byte address of p)+isizeof(T)p + i \;\equiv\; (\text{byte address of } p) + i\cdot \texttt{sizeof}(T)

This is why the equivalence holds:


HOW the compiler computes it

Figure — Pointer arithmetic — adding integers to pointers

Forecast-then-Verify

Recall Forecast before peeking

int a[3]; int *p = a; If &a[0] is 0x200 and sizeof(int)==4, what address does p + 2 hold? And what about ((char*)p) + 2?

Verify:

  • p + 20x200 + 2*4 = 0x208 (points at a[2]).
  • ((char*)p) + 20x200 + 2*1 = 0x202 (points into the middle of a[0]! Usually a bug.)

Common mistakes (Steel-man + fix)


80/20 — the one rule that unlocks everything


Feynman

Recall Explain to a 12-year-old

Imagine a row of identical lockers in a hallway. A pointer is like saying "I'm standing in front of locker #5." If I say "+1", I don't take one step — I move to the next locker, however wide that locker is. Tiny lockers (chars) = one step; fat lockers (doubles) = a big stride. The pointer always knows how wide its lockers are, so "+1" always lands neatly in front of the next one — never stuck halfway between two.


Active Recall

What does p + 1 add to the address, in bytes?
sizeof(*p) bytes (one element), not 1 byte.
arr[i] is exactly equivalent to which pointer expression?
*(arr + i) (and also *(i+arr), i[arr]).
For int *p with sizeof(int)==4, how many bytes does p + 3 move?
3 * 4 = 12 bytes.
Is p + q (two pointers) legal?
No. Only pointer ± int and pointer - pointer are defined.
Why is ((char*)p)+1 different from p+1 for an int *p?
Casting to char* makes stride = 1 byte, so it advances only 1 byte instead of sizeof(int).
What is the difference between *p + 1 and *(p+1)?
*p + 1 = the value at p, plus 1. *(p+1) = the value of the next element. * binds tighter than +.
Is forming arr + N (one past the last element) legal? Is dereferencing it legal?
Forming it is legal; dereferencing it is undefined behavior.
What general rule covers 80% of pointer arithmetic?
p + n moves n * sizeof(*p) bytes and lands on element n — "step by type, not by byte."

Connections

Concept Map

knows

multiplies

computes

requires

motivates

makes true

written as

allows

via

enables

Pointer to type T

sizeof T stride

Scaled arithmetic p plus n

Byte address A plus n times s

Arrays stored contiguously

Lands on element boundary

Array pointer identity

Plus is commutative

i bracket arr legal

Walk array with p plus plus

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, pointer sirf ek address nahi hota — wo address ke saath ye bhi yaad rakhta hai ki jis cheez pe point kar raha hai uska size kitna hai. Isliye jab tum p + 1 likhte ho, C 1 byte add nahi karta; wo 1 * sizeof(*p) bytes add karta hai. Matlab agar p ek int* hai aur int 4 byte ka hai, to p + 1 4 bytes aage jaata hai aur seedha agle element pe land karta hai, beech mein kahin nahi.

Yaad rakhne ka mantra: "Step by TYPE, not by BYTE." Locker wali example socho — tum locker #5 ke saamne khade ho, "+1" bolne par ek kadam nahi, balki agle locker ke saamne chale jaate ho, locker chahe patla ho (char) ya mota (double). Isi wajah se arr[i] aur *(arr + i) bilkul same cheez hai — compiler dono ko ek hi tareeke se scale karta hai.

Galtiyaan jo sab karte hain: p + 1 ko 1 byte samajh lena (galat — wo sizeof jitna jump hai), do pointers ko add karne ki koshish (illegal — sirf pointer±int aur pointer-pointer chalta hai), aur *p + 1 ko *(p+1) samajh lena (* ki precedence zyada hai, dono alag hain). Aur ek baat: array ke 0 se N-1 tak hi deref karo; arr + N banana legal hai par usse deref karna undefined behaviour hai. Bas ye ek rule — n * sizeof(*p) — pakad lo, to 80% pointer sawaal khud solve ho jayenge.

Go deeper — visual, from zero

Test yourself — C Programming

Connections