CS Atlas GATE 2027
PDS course
0 / 103 complete

PDS/Phase 1 · Programming in C

Lesson 1.5.1 · Item 25 of 103

1-D arrays; a[i] == *(a+i) == i[a]; arrays decaying to pointers; passing arrays to functions; the sizeof trap

Read at your own pace. Try the questions before opening the answers.

On this page

0 · Recall Warm-up

Answer from memory first. Answers are in the Answer Vault at the bottom.

  • An int *p holds 2000. What does p + 3 hold? from Lesson 1.4.3
  • What does *p mean 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, so int 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

Diagram: a · 1 · [0] · 1000 · 2 · [1] · 1004 · 3 · [2] · 1008 · 4 · [3] · 1012 · 5 · [4] · 1016 · a, &a[0] · p = a + 1 · a + 3

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

Ready for the next idea?

Mark this item complete when you’ve finished reading and working through it.