0 · Recall Warm-up
Answer from memory first. Answers are in the Answer Vault at the bottom.
- After
void f(int *p, int *q) { p = q; *p = 2; }is called with &i, &j, which variable becomes 2? from Lesson 1.4.2 - What is kept in a stack frame? from Lesson 1.3.3
- In a switch with no breaks, entering at case 2 runs which cases? from Lesson 1.2.1
1 · The Hook
🎣
Houses on a street are numbered by plot, not by step: walking “one house further” is 1 house, however wide the house is. In memory, an int occupies 4 byte-boxes and a double 8. So moving a pointer “one int further” must jump 4 bytes, and “one double further” 8 bytes. C does this scaling for you.
2 · Predict First
🤔
An int *p holds the address 2000. What address does p + 3 hold? And if p were a double *?
Make a guess in your head. The answer opens Section 3.
3 · Core Concept
💡
Predict First — the answer
2012 for int (3 × 4 bytes) and 2024 for double (3 × 8). p + k moves k elements, not k bytes.
p + k scales by the element size
If p points to type T, p + k is the address k elements further: address(p) + k × sizeof(T). Likewise p − k, p++ (move to the next element) and p--.
| p holds 2000, type | sizeof | p + 3 |
|---|---|---|
char * | 1 | 2003 |
short * | 2 | 2006 |
int * | 4 | 2012 |
double * | 8 | 2024 |
Measured on our machine by converting to char * (which steps one byte):
int x;
double d;
char c;
int *pi = &x;
double *pd = &d;
char *pc = &c;
printf("%d %d %d\n", (int)((char *)(pi + 1) - (char *)pi),
(int)((char *)(pd + 1) - (char *)pd),
(int)((char *)(pc + 1) - (char *)pc));
Output
4 8 1
Subtracting and comparing pointers
For two pointers into the same block of consecutive elements, q − p is the number of elements between them (not bytes), and <, >, == compare positions.
int x;
int *p = &x;
int *q = p + 1; /* one past x: allowed to compute and compare */
printf("%d %d\n", (int)(q - p), q > p);
Output
1 1
A pointer may point one element past an object (to compare), but must not be dereferenced there. Arithmetic is meaningful only inside a row of consecutive elements; the next chapter gives you such rows.
No meaningless arithmetic
Adding two pointers, multiplying or dividing them is not allowed. Only pointer ± integer, pointer − pointer, and comparisons.
* together with ++
Post-increment p++ binds tighter than *; pre-increment ++p and * share a level and group right to left:
| Expression | Means | Effect |
|---|---|---|
*p++ | *(p++) | value at p, then p moves to the next element |
*++p | *(++p) | p moves first, then the value at the new place |
++*p | ++(*p) | the pointed-to value grows by 1; p stays |
(*p)++ | (*p)++ | gives the old value, then the pointed-to value grows; p stays |
int x = 5;
int *p = &x;
int y = ++*p; /* ++(*p): x becomes 6, y = 6 */
int z = (*p)++; /* z = 6, then x becomes 7 */
printf("%d %d %d\n", x, y, z);
Output
7 6 6
4 · Visual
int *p = 2000: each step of +1 jumps one 4-byte element, so p + 3 is 2012.
byte addresses: 2000 2001 2002 2003 | 2004 ... 2007 | 2008 ... 2011 | 2012 ...
[ int #0 ][ int #1 ][ int #2 ][ int #3 ...
^p ^p+1 ^p+3
as char *: p + 3 = 2003 (one byte per step)
as int *: p + 3 = 2012 (four bytes per step)
as double*: p + 3 = 2024 (eight bytes per step)
The same “+3” means a different number of bytes for each pointer type.
5 · Worked Examples
Example 1 Easy
A short *s holds 3000 and a long long *t holds 3000 (sizes 2 and 8). What do s + 5 and t + 5 hold?
Solution
3000 + 5 × 2 = 3010; 3000 + 5 × 8 = 3040.
Example 2 Medium
int *p holds 4000 and int *q holds 4020, both inside the same row of ints. What is q − p? What address is p + (q − p)/2?
Solution
The difference counts elements: (4020 − 4000)/4 = 5. Then (q − p)/2 = 2 (integer division), and p + 2 = 4008.
Example 3 GATE
What does this print?
int x = 5;
int *p = &x;
int y = ++*p; /* ++(*p): x becomes 6, y = 6 */
int z = (*p)++; /* z = 6, then x becomes 7 */
printf("%d %d %d\n", x, y, z);
Solution
++*p is ++(*p): x becomes 6 and y = 6. (*p)++ gives the old value 6 to z and then x becomes 7. p never moves.
Output
7 6 6
6 · GATE Traps
⚠️
- p + 1 adds sizeof(*p) bytes, not 1 byte (except for char *).
- q − p counts elements, not bytes.
*p++moves the pointer;(*p)++changes the value.- Adding two pointers is not allowed; subtracting them is.
- Pointer arithmetic outside one row of elements (other than one past the end) is undefined.
8 · Memory Hook
🧠
“Pointers count houses, not bricks.” +1 always means “next house of my kind”, whatever its width.
9 · Connect the Dots
Lessons 1.4.1–1.4.3 covered addresses, passing them, and stepping them by element size. Stepping only makes sense when many values of one type sit side by side. Next lesson answers: how do we declare a whole row of values at once and walk through it with an index or a pointer?
10 · Self-Test
GATE format. Try every question before opening the vault.
Q1NAT1 markScaling
A double *d holds 1000. What address does d + 4 hold? (double = 8 bytes)
Numerical answer: ________
Q2NAT1 markDifference
Two int * pointers into one row of ints hold 2016 and 2040. What is their difference (larger − smaller)?
Numerical answer: ________
Q3MCQ2 marksOutput
What does this print?
int x = 10;
int *p = &x;
int a = (*p)++;
int b = ++*p;
printf("%d %d %d\n", a, b, x);
- (A)
11 11 12 - (B)
10 11 11 - (C)
11 12 12 - (D)
10 12 12
Q4MCQ1 markPrecedence
*p++ means:
- (A) *(p++)
- (B) *(++p)
- (C) ++(*p)
- (D) (*p)++
Q5MSQ1 markRules
Which pointer operations are allowed in C (pointers into the same row of ints)?
- (A) p + q
- (B) p + 3
- (C) q − p
- (D) p < q
11 · Rule Card
- p + k = address + k × sizeof(*p); p++ moves one element.
- q − p = number of elements between (same row).
- Allowed: ptr ± int, ptr − ptr, comparisons. Not: ptr + ptr, ×, ÷.
- *p++ = *(p++); *++p = *(++p); ++*p = ++(*p); (*p)++ changes the value, p stays.
- One past the end may be computed/compared, never dereferenced.
12 · Concept Ledger
Unlocked in this lesson. From here on, these terms may be used.
pointer arithmeticscaling by sizeofpointer differencepointer comparison*p++ vs (*p)++ vs ++*p vs *++p
13 · Answer Vault
Answer Vault
Try the questions first. Open when you are ready to check.
Recall Warm-up
- j.
- Parameters, automatic locals, the return address and bookkeeping.
- Case 2 and every case and default written below it.
Self-Test
Q1 Answer: 10321 mark
1000 + 4 × 8 = 1032.
Re-read: Lesson 1.4.3 — Pointer arithmetic and why it scales by type size
Q2 Answer: 61 mark
(2040 − 2016)/4 = 6 elements.
Re-read: Lesson 1.4.3 — Pointer arithmetic and why it scales by type size
Q3 Answer: (D)2 marks
(*p)++ gives 10, x → 11; ++*p makes x 12 and gives 12.
Output
10 12 12
- (A) is wrong: a gets the old value.
- (B) is wrong: x is incremented twice.
- (C) is wrong: Post-increment gives the old value 10.
Re-read: Lesson 1.4.3 — Pointer arithmetic and why it scales by type size
Q4 Answer: (A)1 mark
Post-increment ++ binds tighter than *.
- (B) is wrong: That is *++p.
- (C) is wrong: That is ++*p.
- (D) is wrong: That increments the value.
Re-read: Lesson 1.4.3 — Pointer arithmetic and why it scales by type size
Q5 Answer: (B) (C) (D)1 mark
Adding two pointers has no meaning.
- (A) is wrong: Pointer + pointer is not allowed.
Re-read: Lesson 1.4.3 — Pointer arithmetic and why it scales by type size