Arrays in C: Declaration, Initialization and Worked Examples

Learn how C arrays behave through exact contents, safe loop bounds, function calls and two-dimensional traversal. A complete program traces sum, average and maximum.

Prashant Jain

KnowledgeGate AI educator

Updated 17 Jul 20266 min read

A declaration such as int marks[5] looks simple, but zero-based indexes, fixed bounds, initialization, traversal and function parameters cause most early mistakes. This guide builds those ideas through exact array contents, a compile-ready program that finds a sum, average and maximum, a two-dimensional example, and exercises with checkable answers. The aim is to make every boundary and result predictable. If you are building a wider programming foundation, Coding & DSA Courses for Placements places C alongside the next problem-solving skills.

Arrays in C: what they store and why indexes start at zero

An array stores a contiguous sequence of elements of one type. Instead of declaring five unrelated variables, write:

int marks[5] = {72, 81, 69, 90, 78};

The name marks identifies five elements: marks[0] = 72, marks[1] = 81, marks[2] = 69, marks[3] = 90 and marks[4] = 78. Indexing starts at zero, so length 5 gives valid indexes 0 through 4.

marks[5] is outside the array, and accessing it has undefined behaviour. A loop changes one index to process all five marks; separate variables need five statements.

Declaring and initializing one-dimensional C arrays

In int marks[5];, int is the element type, marks is the name and 5 is the count. An automatic local array starts with indeterminate elements, so initialize them before reading.

These common initialization forms produce different but predictable contents:

int marks[5] = {72, 81, 69, 90, 78}; // [72, 81, 69, 90, 78]
int zeros[5] = {0};                  // [0, 0, 0, 0, 0]
int partial[5] = {4, 9};             // [4, 9, 0, 0, 0]
int primes[] = {2, 3, 5, 7, 11};     // inferred length: 5

Where the real array object is visible, size_t count = sizeof marks / sizeof marks[0]; gives 5. Do not use this as a general solution in a function parameter, where an array parameter is adjusted to a pointer.

A five-cell contiguous memory strip for int marks[5] = {72, 81, 69, 90, 78}; label the cells with indexes 0, 1, 2, 3, 4, values 72, 81, 69, 90, 78, and illustrative addresses 1000, 1004, 1008, 1012, 1016 under the explicit assumption that this example's int occupies 4 bytes.

These addresses are illustrative, not portable. The example assumes a four-byte int only to show contiguous placement.

Reading, updating and traversing an array with loops

With int marks[5] = {72, 81, 69, 90, 78};, marks[2] is 69. After marks[2] = 74;, the array is [72, 81, 74, 90, 78].

A forward traversal is:

for (size_t i = 0; i < count; i++)
    printf("%d ", marks[i]);

It prints 72 81 74 90 78. Use i < count, not i <= count, because count is not a valid index. Reverse safely with:

for (size_t i = count; i > 0; i--)
    printf("%d ", marks[i - 1]);

This prints 78 90 74 81 72. Here i - 1 moves from index 4 to 0, and the loop stops before unsigned size_t goes below zero. Repeated comparisons and swaps lead naturally to Sorting Algorithms: Complexity and Comparison.

Worked C array program: sum, average and maximum

This runnable program derives the length and updates the sum and maximum in one loop:

#include <stdio.h>

int main(void) {
    int scores[] = {18, 24, 15, 27, 21, 30};
    size_t n = sizeof scores / sizeof scores[0];
    int sum = 0;
    int max = scores[0];
    size_t max_index = 0;

    for (size_t i = 0; i < n; i++) {
        sum += scores[i];
        if (scores[i] > max) {
            max = scores[i];
            max_index = i;
        }
    }

    double average = (double) sum / n;
    printf("sum=%d, average=%.2f, max=%d, max_index=%zu\n",
           sum, average, max, max_index);
    return 0;
}

The loop develops as follows:

Index

scores[index]

Running sum

Current max

Max index

0

18

18

18

0

1

24

42

24

1

2

15

57

24

1

3

27

84

27

3

4

21

105

27

3

5

30

135

30

5

A six-step trace table for scores = {18, 24, 15, 27, 21, 30} with columns index, scores[index], running sum, current max, and max index; rows show (0,18,18,18,0), (1,24,42,24,1), (2,15,57,24,1), (3,27,84,27,3), (4,21,105,27,3), and (5,30,135,30,5), followed by average = 135 / 6 = 22.50.

The arithmetic is 18 + 24 + 15 + 27 + 21 + 30 = 135, then 135 / 6 = 22.5. Output is sum=135, average=22.50, max=30, max_index=5. The strict > comparison retains the first occurrence of a tied maximum.

Passing arrays to C functions without losing the length

Pass the element count with the array:

int sum_array(const int values[], size_t n) {
    int total = 0;
    for (size_t i = 0; i < n; i++)
        total += values[i];
    return total;
}

const promises that the function will not modify elements through values. At the caller:

int readings[] = {12, 15, 9, 14};
size_t n = sizeof readings / sizeof readings[0];
int total = sum_array(readings, n);

The total moves 0 -> 12 -> 27 -> 36 -> 50, so sum_array(readings, 4) returns 50. In a parameter, int values[] becomes int *values, so the length is not received automatically. sizeof values / sizeof values[0] would use the pointer size, not the caller's element count. Pass n explicitly.

Two-dimensional arrays in C: rows, columns and nested loops

int sales[2][3] = {{5, 7, 9}, {6, 8, 10}}; creates two rows and three columns. Here sales[0][1] is 7, while sales[1][2] is 10.

Nested loops keep each bound clear:

int grand_total = 0;
for (size_t row = 0; row < 2; row++) {
    int row_sum = 0;
    for (size_t col = 0; col < 3; col++)
        row_sum += sales[row][col];
    grand_total += row_sum;
}

Row 0 totals 5 + 7 + 9 = 21, row 1 totals 6 + 8 + 10 = 24, and the grand total is 45. Row-major order is 5, 7, 9, 6, 8, 10: row 0 precedes row 1 in memory.

Common C array errors and three exercises with answer checks

Most array bugs come from these causes:

Error

Consequence

Fix

for (i = 0; i <= 5; i++) for five elements

Reaches invalid index 5

Use i < 5

Read int data[3]; before assignment

Uses indeterminate values

Initialize before reading

Use a = b; for two arrays

Whole-array assignment is not permitted

Copy elements in a loop or use a suitable library routine

Use scanf("%d", values[i])

Omits the element's address

Validate the index, then use scanf("%d", &values[i]) and check its result

int a[3] = {1, 2, 3, 4}; requires a diagnostic because four values cannot fit three elements. In contrast, int a[3] = {1, 2}; is valid and zero-fills the remainder.

How arrays in C are tested

Try these before checking answers. Reverse {3, 8, 1, 6, 4} to get {4, 6, 1, 8, 3}. For {10, 20, 30, 40}, get average 25.0 and 2 elements above it. For {{2, 1, 0}, {4, 3, 5}, {7, 8, 6}}, the main diagonal is 2 + 3 + 6 = 11.

Extend this with about 30 published C Array Basics questions. Arrays also support bounded push, pop, enqueue and dequeue operations; Stacks and Queues: Operations and Uses shows why index checks matter.

Arrays in C: the short version and next practice

Keep five rules in view:

  1. Declare the correct element count.

  2. Initialize elements before reading them.

  3. Keep every index between 0 and n - 1.

  4. Derive the length only where the real array object is visible.

  5. Pass the length explicitly into functions.

The scores total 135, average 22.50, and have maximum 30 at index 5; the 2 x 3 sales array totals 45. For the complete language sequence and more practice, continue with C Language Course: Concepts, MCQs and Coding.

As a final check, change scores[2] from 15 to 33. Predict the new total 153, average 25.50, maximum 33, and maximum index 2, then rerun the program and verify each value.

Discussion