Arrays and indexing
An array is one unbroken block of equal-sized cells, and a[i] is just arithmetic on the address of the first cell. Everything GATE asks about arrays (address of an element, partial initialisation, sizeof, shifting, off-by-one) follows from that one fact.
Why it exists
A program often has many values of the same kind: the marks of 60 students, the pixels of a row, the digits of a number. Declaring 60 separate variables is impractical, and no loop could visit them. An array gives one name to a whole sequence and lets the program pick an element by a number, its index.
The machine reason it works so well is that the elements sit side by side in memory. To reach element number the computer does not search: it multiplies and adds. That makes access a constant-time operation, and it is why arrays are the foundation under strings, matrices, heaps and hash tables.
Prerequisites
Precise definitions
- Array. A sequence of objects of the same type, stored in contiguous memory.
int a[5];declares five ints. The number of elements is part of the array's type:int[5]andint[6]are different types. - Index. Elements are numbered from 0. The valid indices of
a[5]are 0, 1, 2, 3, 4. There is no index 5. - No bounds checking. C never checks an index. Reading or writing
a[5]ora[-1]is undefined behaviour: it may crash, print garbage, or silently corrupt a neighbouring variable. - Size.
sizeof ais . The number of elements issizeof a / sizeof a[0]. This works only whereareally is an array (not a function parameter, see the functions page). In this course anintis 4 bytes, as on typical gcc platforms; the standard only requires a minimum, so GATE questions state it. - Address of an element. If the array starts at address and each element takes bytes, then
This is the whole idea of an array. The lower bound is 0 in C. In the language-neutral questions GATE often asks, the lower bound can be any integer, and the formula becomes . The number of elements of an array with bounds is .
- Subscript is pointer arithmetic. By definition (C11 6.5.2.1),
a[i]means*(a + i). The array nameain an expression becomes a pointer to its first element (it decays), and adding to a pointer moves it by elements. Because+is commutative,i[a]is the same thing. Nobody writes it, but a trap question may. The pointers page explains the arithmetic in full. - When the name does not decay. An array expression keeps its array nature only as the operand of
sizeofor of unary&(C11 also lists_Alignof), and a string literal that initialises an array keeps it too. In every other expression it turns into a pointer. - Initialisation (C11 6.7.9).
int a[5] = {1, 2};sets . Elements without an initialiser are set to zero.int a[5] = {0};sets all five to zero.int a[] = {1, 2, 3};lets the compiler count: the array has 3 elements.- An array with static storage duration (global or
static) that has no initialiser is entirely zero. - A local (automatic) array with no initialiser contains indeterminate values. Reading them is a bug.
- Arrays are not first-class values. You cannot assign one array to another (
b = a;is an error), you cannot return an array from a function (astructthat contains an array can be copied and returned), anda == bon two arrays compares their addresses, not their contents. To copy contents you loop or usememcpy.
How it works
Step through the program below. It is a real run: the addresses are read from the running machine. The one fact to see is the address column. Each cell is exactly 4 higher than the one before it, so a[i] needs no search, only "start + i × 4".
An array is one block of equal cells
Real run, real addressesC source
Stack
aint
Amber = changed in this step. Hover a cell for its full address. Arrows show where a pointer points; the small tag under a cell names the pointers aimed at it.
Step 1
a is five ints side by side in one block. Look at the addresses: each is 4 higher than the one before, because an int is 4 bytes.
Things to notice:
- The variable
iis a separate object. It is not part of the array. The array is only the five cells. - Writing
a[i + 2]uses an expression as the index. Any integer expression is allowed. - The loop reads the cells in order, so the memory is walked in order. This is also the reason arrays behave well with caches, which the COA subject returns to.
Operations and their cost
| Operation | Cost | Why |
|---|---|---|
Read or write a[i] | one multiplication and one addition | |
| Search an unsorted array | may have to look at every cell | |
| Binary search a sorted array | halves the range each time (it needs random access, which arrays give) | |
| Insert at the end (room available) | write one cell | |
| Insert at position | the cells from onward must each shift one place | |
| Delete at position | the cells after must each shift back |
Worked examples
EX 1Size, count and the stride between elements
Easy#include <stdio.h>
int main(void) {
int a[5] = {10, 20, 30, 40, 50};
printf("%zu %zu %td\n", sizeof a, sizeof a / sizeof a[0],
(char *)&a[1] - (char *)&a[0]);
return 0;
}Output (with a 4-byte int):
20 5 4Reading it. sizeof a is bytes. Dividing by the size of one element gives the count, 5. Casting both addresses to char * makes the subtraction count bytes: neighbouring ints are 4 bytes apart, exactly what the animation showed.
EX 2Partial initialisation and zero by default
Easy#include <stdio.h>
int g[3];
int main(void) {
int a[6] = {1, 2, 3};
int b[] = {4, 5, 6, 7};
for (int i = 0; i < 6; i++) printf("%d ", a[i]);
printf("\n%zu %d %d %d\n", sizeof b / sizeof b[0], g[0], g[1], g[2]);
return 0;
}Output:
1 2 3 0 0 0
4 0 0 0Reading it. a lists three values for six cells, so the remaining three are zero. b has no size, so the compiler counts the four initialisers. The global g has static storage duration and no initialiser, so all three cells are zero. A local array declared as int c[3]; would hold indeterminate values instead.
EX 3a[i] and *(a + i) and i[a]
Medium#include <stdio.h>
int main(void) {
int a[4] = {5, 6, 7, 8};
printf("%d %d %d\n", a[2], *(a + 2), 2[a]);
return 0;
}Output:
7 7 7Reading it. The standard defines a[2] to be *(a + 2). Addition is commutative, so 2 + a is the same address as a + 2, which is why 2[a] is also legal and equal. If a question writes the index and the array name the wrong way round, it is still the same element.
EX 4Insertion shifts cells, and the shifts can be counted
Medium#include <stdio.h>
int main(void) {
int a[6] = {10, 20, 30, 40};
int n = 4, pos = 2, x = 25, shifts = 0;
for (int i = n; i > pos; i--) {
a[i] = a[i - 1];
shifts++;
}
a[pos] = x;
n++;
for (int i = 0; i < n; i++) printf("%d ", a[i]);
printf("\n%d\n", shifts);
return 0;
}Output:
10 20 25 30 40
2Reading it. To open a gap at index 2, the cells after it move right, starting from the last one. If the loop went left to right, a[3] = a[2] would overwrite 40 before it was copied. The shift count is : inserting near the front is expensive, inserting at the end costs no shifts.
EX 5Address of an element with a non-zero lower bound
GATE levelAn array A[-5 .. 10] has 4-byte elements and starts at address 1000. Find the address of A[3], the address of the last element, and the total size.
Count the elements. .
Address of . .
Last element : .
Total size. bytes, so the array covers addresses 1000 to 1063.
Check by position. A[3] is the 9th element (positions run , which is 9 values), so it is 8 elements after the first: . The same.
EX 6The order of an in-place update matters
GATE level#include <stdio.h>
int main(void) {
int f[5] = {1, 2, 3, 4, 5};
int r[5] = {1, 2, 3, 4, 5};
for (int i = 1; i < 5; i++) f[i] = f[i] + f[i - 1];
for (int i = 4; i >= 1; i--) r[i] = r[i] + r[i - 1];
for (int i = 0; i < 5; i++) printf("%d ", f[i]);
printf("\n");
for (int i = 0; i < 5; i++) printf("%d ", r[i]);
printf("\n");
return 0;
}Output:
1 3 6 10 15
1 3 5 7 9Forward loop. f[i - 1] has already been updated when f[i] is computed, so each cell receives the running total (a prefix sum): 1, 3, 6, 10, 15.
Backward loop. r[i - 1] has not yet been updated when r[i] is computed, so each cell receives only the sum of itself and its original left neighbour: 1, 3, 5, 7, 9.
How to solve this kind of question. Write the array on one line. Perform the loop one iteration at a time, rewriting the changed cell. Never compute all iterations "at once" from the original values unless nothing read has been modified.
Cheat box
Cheat box
int a[n]has indices .a[n]is out of bounds (undefined behaviour).- Address: (C), or (lower bound ). Count: .
sizeof a; elementssizeof a / sizeof a[0](only for a true array, never for a parameter).a[i]*(a + i)i[a].{1, 2}for 5 cells gives1 2 0 0 0.{0}zeroes everything. Globals and statics start at zero. Local arrays start with garbage.- Arrays cannot be assigned, returned, or compared with
==for contents. - Access . Search . Binary search (sorted). Insert or delete at : .
Traps and GATE patterns
Connections
Unlocks
Across subjects
The formula is the same base plus scaled index calculation that a CPU performs in an indexed addressing mode. Where an array lives (stack, data, heap) is explained on the memory layout page. Two-dimensional arrays extend the same formula and are the subject of multidimensional arrays.
PYQs
5 previous year questions from your book. I re-solved each one myself (5 by running or simulating, 0 by reasoning only); the book's key is shown next to my answer. All PYQs
Consider the following C function in which size is the
number of elements in the array E: The value returned
by the function MyX is the
int MyX(int *E, unsigned int size)
{
int Y = 0;
int Z;
int i, j, k;
for(i = 0; i< size; i++)
Y = Y + E[i];
for(i = 0; i< size; i++)
for(j = i; j < size; j++)
{
Z = 0;
for(k = i; k <= j; k++)
Z = Z + E[k];
if (Z > Y)
Y=Z;
}
return Y;
}
The value returned by the function MyX is the- (a)maximum possible sum of elements in any sub- array of array E
- (b)maximum element in any sub-array of array E
- (c)sum of the maximum elements in all possible sub-arrays of array E
- (d)the sum of all the elements in the array.
The following function computes the maximum value
contained in an integer array
p[] of size n (n >= 1).
int max(int *p, int n) {
int a=0, b=n-1;
while (__________)
{
if (p[a] <= p[b])
{
a = a+1;
}
else
{
b = b-1;
}
}
return p[a];
}
The missing loop condition is- (a)a != n
- (b)b != 0
- (c)b > (a + 1)
- (d)b != a
Let A be a square matrix of size n × n. Consider the
following pseudocode. What is the expected output?
C = 100;
for i = 1 to n do
for j = 1 to n do
{
Temp = A[i] [j] + C;
A [i] [j] = A[j] [i];
A[j][i] = Temp – C;
}
for i = 1 to n do
for j = 1 to n do
output (A[i][j]);- (a)The matrix A itself
- (b)Transpose of the matrix A
- (c)Adding 100 to the upper diagonal elements and subtracting 100 from lower diagonal elements of A
- (d)None of the above
A Young tableau is a 2D array of integers increasing from left to right and from top to bottom. Any unfilled entries are marked with ∞, and hence there cannot be any entry to the right of, or below a ∞. The following Young tableau consists of unique entries. When an element is removed from a Young tableau, other elements should be moved into its place so that the resulting table is still a Young tableau (unfilled entries may be filled with a ∞). The minimum number of entries (other than 1) to be shifted, to remove 1 from the given Young tableau is .
Suppose c = ⟨c[0], ..., c[k-1]⟩ is an array of length k,
where all the entries are from the set {0,1}. For any
positive integers a and n, consider the following
pseudocode.
DOSOMETHING (c, a, n)
z←1
for i←0 to k-1
do z←z2 mod n
if c[i]=1
then z←(z×a) mod n
return z
If k = 4, c = ⟨1, 0, 1, 1⟩, a = 2, and n = 8
then the output of DO SOMETHING (c, a, n) is
.
DATA STRUCTURESelf-check
Question 1
What does this print?
#include <stdio.h>
int main(void) {
int a[4] = {1, 2};
int s = 0;
for (int i = 0; i < 4; i++) s += a[i];
printf("%d %zu\n", s, sizeof a);
return 0;
}Show answerHide
The array has 4 cells even though only 2 initialisers are given. The other two are zero, so . The size is bytes.
3 16Question 2
An array has 8 elements of 2 bytes each, and its first element is at address 500 (indices start at 0). What is the address of the element with index 5, and which addresses does the whole array cover?
Show answerHide
. The array is bytes, so it covers addresses 500 to 515.
Question 3
How many elements does A[-3 .. 4] have, and what is the address of A[4] if the base is 200 and each element is 8 bytes?
Show answerHide
elements. is at .
Question 4
An array int a[5] and a loop for (i = 0; i <= 5; i++) a[i] = i;. What is wrong, and what can you say about the program's behaviour?
Show answerHide
The last iteration writes a[5], which does not exist. The behaviour is undefined. It might appear to work, overwrite a neighbouring variable, or crash, so no particular output can be promised.
Question 5
You insert a value at index 0 of an array holding elements (with spare room). How many element moves are needed, and how many when you delete the element at index 0?
Show answerHide
Inserting at index 0 shifts all elements one place right, so moves. Deleting the element at index 0 shifts the remaining elements one place left, so moves. Both are .
Revision card
One-screen revision
- Array = contiguous block of equal cells. Indices . No bounds check; out of bounds is undefined.
- Address . Element count .
a[i]is*(a + i). Name decays to a pointer except as the operand ofsizeofor&, and for a string literal initialising an array.- Partial initialiser: the rest is zero. Local without initialiser: garbage. Global: zero.
- Cannot assign arrays or compare contents with
==. - Insert or delete in the middle shifts cells: . Index access is .
- In-place loops: decide whether each read sees the old or the new value.
References
- ·Kernighan and Ritchie, The C Programming Language, 2nd ed., Section 1.6 Arrays, Section 5.3 Pointers and Arrays, Section 4.9 Initialization
- ·ISO/IEC 9899:2011 (C11), Sections 6.2.5 Types (array types), 6.3.2.1 Lvalues, arrays, and function designators, 6.5.2.1 Array subscripting, 6.5.3.4 The sizeof operator, 6.5.6 Additive operators, 6.7.6.2 Array declarators, 6.7.9 Initialization
Verification
The animation replays a real run of an instrumented C program: every address and value is read from memory at each step, and the test suite checks that neighbouring ints are exactly 4 bytes apart. All C programs on this page are compiled with -Wall -Wextra -Werror and run by npm run verify:c. The textbook section numbers were written from memory and have NOT been checked against the books. The prose, the address-calculation formulas and the GATE-pattern claims have NOT yet had a human textbook check (the independent second pass is described at the end of these notes). SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand (long C programs were not re-read line by line: they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose). No defect found. Status raised to self-checked; verified needs a textbook or human check.
last verified: never
My notes (saved in this browser)