0 · Recall Warm-up
Answer from memory first. Answers are in the Answer Vault at the bottom.
- An
int *pholds 2000. What doesp + 3hold? from Lesson 1.4.3 - What does
*pmean in an expression? from Lesson 1.4.1 - How many times does the body of
for (i = 0; i < n; i++)run? from Lesson 1.2.2
1 · The Hook
🎣
A class of 60 students has 60 marks. Sixty separate variables (m1, m2, …, m60) cannot be processed by a loop, because a loop cannot change a variable’s name. An array is one name for a row of boxes of the same type, side by side in memory, picked out by a number: marks[0], marks[1], … The number can be a variable, so a loop can visit every box.
2 · Predict First
🤔
What does this print?
int a[5] = {10, 20, 30};
printf("%d %d %d\n", a[3], a[4], a[1]);
Make a guess in your head. The answer opens Section 3.
3 · Core Concept
💡
Predict First — the answer
Output
0 0 20
Indices start at 0, so a[1] is 20. When an initializer list is shorter than the array, the remaining elements are set to 0: a[3] and a[4] are 0.
Declaring and indexing
int a[5]; reserves 5 consecutive ints, a[0] to a[4]. The size must be a constant here. a[i] is the element at index i. Using an index outside 0 … 4 is undefined behavior: C does not check.
Initialization
int a[5] = {1, 2, 3, 4, 5};int a[5] = {10, 20};— the rest become 0, soint a[100] = {0};zeroes everything.int a[] = {4, 8, 15};— the size (3) comes from the list.- Arrays cannot be assigned as a whole:
a = b;is an error. Copy element by element.
Arrays in memory and the address formula
Element i of an array starting at address B with element size w is at B + i × w. This is exactly pointer arithmetic from Lesson 1.4.3.
a[i] is *(a + i)
In almost every expression the array name decays to a pointer to its first element: a becomes &a[0]. C defines a[i] as *(a + i). Since addition is commutative, i[a] means the same thing (legal, though nobody writes it), and any pointer can be indexed: p[i] is *(p + i).
int a[4] = {3, 6, 9, 12};
int *p = a;
printf("%d %d %d %d\n", a[2], *(a + 2), 2[a], p[2]);
Output
9 9 9 9
When an array does not decay
Two exceptions: sizeof a gives the size of the whole array (20 bytes for int a[5]), and &a is a pointer to the whole array, so &a + 1 jumps past all 20 bytes while a + 1 moves 4 bytes.
int a[5];
printf("%d %d\n", (int)((char *)(a + 1) - (char *)a), (int)((char *)(&a + 1) - (char *)a));
Output
4 20
The array name is not a variable: a++ is an error, but a pointer copy p = a; p++; is fine.
Passing an array to a function
An array argument decays to a pointer, so the function receives the address of the first element. void f(int a[]) and void f(int *a) are identical. The function can therefore change the caller’s elements, and it cannot know the length: pass it separately.
void doubleAll(int *v, int n)
{
int i;
for (i = 0; i < n; i++)
v[i] = v[i] * 2;
}
int main(void)
{
int a[3] = {1, 5, 7};
doubleAll(a, 3);
printf("%d %d %d\n", a[0], a[1], a[2]);
return 0;
}
Output
2 10 14
The sizeof trap
Inside the function the parameter is a pointer, so sizeof(a) gives the pointer size, not the array size:
void f(int a[])
{
printf("in f: %u\n", sizeof(a));
}
int main(void)
{
int a[5] = {0};
printf("in main: %u, elements: %u\n", sizeof(a), sizeof(a) / sizeof(a[0]));
f(a);
return 0;
}
Output
in main: 20, elements: 5
in f: 4
sizeof(a) / sizeof(a[0]) counts elements only where the real array is visible.
4 · Visual
int a[5] at 1000: a[i] is at 1000 + 4i. The name a stands for &a[0].
Trace of the GATE example (int a[5] = {1,2,3,4,5}; int *p = a + 1;)
statement a[0] a[1] a[2] a[3] a[4] p points to
------------------- ---- ---- ---- ---- ---- -----------
start 1 2 3 4 5 a[1]
*p++ += 10; 1 12 3 4 5 a[2] (add to a[1], then p moves)
*(p + 1) = *p * 2; 1 12 3 6 5 a[2] (a[3] = a[2] * 2)
p[-2] = 0; 0 12 3 6 5 a[2] (p[-2] is a[0])
One row per statement: the elements and where p points.
5 · Worked Examples
Example 1 Easy
What does this print?
int marks[5] = {72, 85, 64, 91, 58};
int i, sum = 0, best = marks[0];
for (i = 0; i < 5; i++) {
sum += marks[i];
if (marks[i] > best) best = marks[i];
}
printf("%d %d\n", sum, best);
Solution
The loop visits marks[0] … marks[4], adding each and keeping the largest.
Output
370 91
Example 2 Medium
What does this print?
int a[] = {4, 8, 15, 16};
int *p = a;
int s = 0;
while (p < a + 4)
s += *p++;
printf("%d\n", s);
Solution
p starts at a and stops when it reaches a + 4 (one past the end, compared but never dereferenced). *p++ reads the element, then moves p: 4 + 8 + 15 + 16.
Output
43
Example 3 GATE
What does this print?
int a[5] = {1, 2, 3, 4, 5};
int *p = a + 1;
*p++ += 10;
*(p + 1) = *p * 2;
p[-2] = 0;
printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);
Solution
See the trace table above: *p++ += 10 adds 10 to a[1] and moves p to a[2]; *(p + 1) = *p * 2 sets a[3] = 3 × 2; p[-2] is a[0].
Output
0 12 3 6 5
6 · GATE Traps
⚠️
- Indices run 0 … n−1; a[n] is outside the array (undefined behavior, no error message).
- A partial initializer zero-fills the rest; an array with no initializer inside a function holds garbage.
- sizeof on an array parameter gives the pointer size (4 here), not the array size.
- a + 1 moves one element; &a + 1 moves past the whole array.
- An array name cannot be assigned or incremented; a pointer copy can.
- Arrays are effectively passed by address: functions can change the caller’s elements.
8 · Memory Hook
🧠
“A street of identical houses.” The array name is the address of house 0; a[i] walks i houses down (*(a + i)). Hand the street to a function and you hand over the address, not the houses.
9 · Connect the Dots
Lesson 1.4.3 needed rows of consecutive elements for pointer arithmetic; arrays are those rows, and a[i] is just *(a + i). Data often comes in tables (seats in rows, marks per subject per student). Next lesson answers: how does C store a table of rows and columns, and how do we find the address of one cell?
10 · Self-Test
GATE format. Try every question before opening the vault.
Q1MCQ1 markEquivalences
For int a[10];, which expression is not the same as a[3]?
- (A)
*(a + 3) - (B)
*(3 + a) - (C)
*a + 3 - (D)
3[a]
Q2MCQ2 marksOutput
What does this print?
int a[6] = {2, 4, 6, 8, 10, 12};
int *p = a + 2, *q = a + 5;
printf("%d %d %d\n", (int)(q - p), *q - *p, p[1] + q[-1]);
- (A)
3 6 18 - (B)
3 6 20 - (C)
3 3 16 - (D)
12 6 18
Q3NAT1 marksizeof
With 4-byte ints and 4-byte pointers, int a[12]; is passed to void f(int a[]). What does sizeof(a) print inside f?
Numerical answer: ________
Q4MSQ1 markArrays
Which statements are true?
- (A)
int a[5] = {1};sets a[1] … a[4] to 0. - (B) An array passed to a function lets the function change the caller’s elements.
- (C) Accessing a[5] of
int a[5]is undefined behavior. - (D)
a++is allowed for an array a.
Q5MCQ2 marksOutput
What does this print?
int a[] = {10, 20, 30, 40, 50};
int *p = a;
p = p + 3;
*p = *(p - 1) + p[1];
p--;
printf("%d %d\n", *p, a[3]);
- (A)
30 80 - (B)
80 30 - (C)
40 80 - (D)
30 70
11 · Rule Card
- int a[n]: indices 0 … n−1; element i at base + i·w.
- Partial initializer zero-fills; int a[] = {…} sizes itself.
- a[i] ≡ *(a + i) ≡ i[a]; p[i] works for any pointer.
- a decays to &a[0] except in sizeof a and &a (whole array).
- Array parameter = pointer: sizeof gives 4 here; pass the length.
- Out-of-range index = undefined; arrays cannot be assigned.
12 · Concept Ledger
Unlocked in this lesson. From here on, these terms may be used.
arrayindexelementinitializer listarray decaya[i] == *(a+i) == i[a]array parametersizeof(a)/sizeof(a[0])
13 · Answer Vault
Answer Vault
Try the questions first. Open when you are ready to check.
Recall Warm-up
- 2012 (3 × 4 bytes).
- The variable p points to.
- n times.
Self-Test
Q1 Answer: (C)1 mark
*a + 3 is a[0] + 3.
- (A) is wrong: That is the definition of a[3].
- (B) is wrong: Addition commutes.
- (D) is wrong: i[a] equals a[i].
Re-read: Lesson 1.5.1 — 1-D arrays; a[i] == *(a+i) == i[a]; arrays decaying to pointers; passing arrays to functions; the sizeof trap
Q2 Answer: (A)2 marks
q − p = 3 elements; *q − *p = 12 − 6 = 6; p[1] + q[−1] = 8 + 10 = 18.
Output
3 6 18
- (B) is wrong: p[1] is a[3] = 8 and q[−1] is a[4] = 10.
- (C) is wrong: The values differ by 6.
- (D) is wrong: Pointer difference counts elements, not bytes.
Re-read: Lesson 1.5.1 — 1-D arrays; a[i] == *(a+i) == i[a]; arrays decaying to pointers; passing arrays to functions; the sizeof trap
Q3 Answer: 41 mark
Inside f, a is a pointer: 4.
Re-read: Lesson 1.5.1 — 1-D arrays; a[i] == *(a+i) == i[a]; arrays decaying to pointers; passing arrays to functions; the sizeof trap
Q4 Answer: (A) (B) (C)1 mark
The array name cannot be incremented.
- (D) is wrong: An array name is not a modifiable variable.
Re-read: Lesson 1.5.1 — 1-D arrays; a[i] == *(a+i) == i[a]; arrays decaying to pointers; passing arrays to functions; the sizeof trap
Q5 Answer: (A)2 marks
p → a[3]: *p = a[2] + a[4] = 30 + 50 = 80. p-- → a[2] = 30.
Output
30 80
- (B) is wrong: *p is printed first.
- (C) is wrong: After p--, p points to a[2].
- (D) is wrong: a[3] becomes 30 + 50 = 80.
Re-read: Lesson 1.5.1 — 1-D arrays; a[i] == *(a+i) == i[a]; arrays decaying to pointers; passing arrays to functions; the sizeof trap