Theory
The secret arrays kept all unit
Small mysteries have piled up. scanf("%s", name) needed no &. The reveal last lesson showed *(p + 2) acting exactly like marks[2].
Time for the confession:
An array's name is not a variable holding values. It is the ADDRESS of box zero.
marks and &marks[0] are the same thing. Once you see it, indexing, pointer walking and half of C's design snap into one picture.
Theory
The coach's name IS its location
Say "coach S4" to a ticket checker and he does not picture sixty berths; he pictures WHERE the coach starts. From there, "berth 23" is a fixed walk. The array name works the same: marks names the starting address, and marks[23] means "start there, walk 23 boxes, open the box". The name is a signpost planted at box zero, and signposts do not move.
Theory
The unification, formally
int marks[5] = {70, 55, 90, 62, 78};
int *p = marks; /* no & needed: marks IS an address */
C defines indexing as pointer arithmetic:
*marks[i] ≡ (marks + i)**
So all of these fetch the same box: marks[2], *(marks + 2), *(p + 2), p[2], yes, even p[2]: indexing works on any pointer.
The one difference that survives: p is a variable (p++ legal, it can walk), while marks is a constant address (marks++ is a compile error, signposts do not move).
Practical
Summing the class with a walking pointer
#include <stdio.h>
int main() {
int marks[5] = {70, 55, 90, 62, 78};
int *p = marks;
int i, total = 0;
for (i = 0; i < 5; i++) {
total += *p; /* read the box */
p++; /* next box */
}
printf("Total: %d\n", total);
return 0;
}This example runs in Gri-Learn on the web, where you can edit it and see the output.
Quiz
Why does int *p = marks; compile WITHOUT an & before marks?
- The array name already evaluates to the address of its first element
- The compiler silently inserts the & for arrays
- It is actually an error that compilers tolerate
- Pointers to arrays never need initialization
Show the answer
The array name already evaluates to the address of its first element
marks IS &marks[0]: an address by definition, so it assigns straight into a pointer. Nothing is inserted or forgiven. The same fact settles the old scanf mystery: scanf("%s", name) works because name already hands over an address, while scanf("%d", &marks) needs & because a plain int variable does not.
Think first
Four spellings, one box
With int marks[5] = {70, 55, 90, 62, 78}; and int p = marks;, evaluate in your head: marks[3], (marks + 3), *(p + 3), p[3]. Then the trick part: which of marks++ and p++ is legal?
Show the answer
All four fetch 62: they are one expression in four costumes, because indexing IS *(base + offset).
p++ is legal (a pointer variable walks); marks++ is a compile error (the array name is a constant address, a planted signpost). That legal/illegal pair is the single most-quoted difference between an array name and a pointer, and a guaranteed exam line.
Quiz
In the walking-pointer code, what does *p give AFTER the loop's third iteration completes (three p++ done)?
- 62, p now points at marks[3]
- 90, p stays at marks[2]
- 70, p returns to the start each round
- Garbage: p left the array
Show the answer
62, p now points at marks[3]
Each p++ plants the pointer one box ahead: after three increments p stands at marks[3], holding 62. It leaves the array only after the FIFTH increment, when the loop has already stopped. Tracking a walking pointer's position round by round is the standard trace question for this topic.
Watch out
Where marks leak
marks++ in an answer: instant error, the name is constant; walk with a separate pointer. sizeof confusion: sizeof(marks) is the WHOLE array (20 bytes here); sizeof(p) is just a pointer's own size, they differ even though marks and p "point to the same place". Walking past the end: the loop bound guards p; lose count of p++ and you are out of bounds, silently.
Theory
Unit 3 closes, and a door opens
Arrays and pointers are now one subject in your head, exactly as C intends. And a promise for Unit 4, next: because an array reaches a function AS AN ADDRESS, functions can modify your actual data, which is the entire story of pass-by-reference. First, though: what a function even is, and why the marks program is begging to be split into them.
Summary
Key takeaways
- The array name IS the address of element zero: marks ≡ &marks[0].
- Indexing is pointer arithmetic: marks[i] ≡ *(marks + i); even p[i] works.
- int *p = marks; needs no &, and p can walk the array with p++.
- marks++ is illegal (constant address); p++ is legal (variable).
- sizeof(marks) = whole array; sizeof(p) = one pointer.
- scanf("%s", name) explained: name is already an address.
- Memory hook: the name is a signpost at box zero, and signposts do not move.