Unit 3 · Lesson 518 minAcademic review pending

Rows and columns

A two-dimensional array is a table. It is stored row by row, and knowing that explains how to loop over it and how to pass it to a function.

Choose explanation

After this lesson

You should be able to

  • Declare and initialise a two-dimensional array.
  • Use nested loops to visit every element in row or column order.
  • Explain why a 2D array parameter must state the number of columns.
01

A table of marks

marks[3][4] holds three rows of four columns — three students, four subjects each. The first subscript picks the row, the second picks the column, so marks[1][2] is the second student's third subject.

Initialise it with nested braces so the shape is visible in the source. It is legal to write one flat list, but then a reader has to count to work out where each row begins.

Three rows, four columns
int marks[3][4] = {
    {72, 45, 91, 38},   /* student 0 */
    {66, 80, 55, 74},   /* student 1 */
    {90, 88, 79, 61}    /* student 2 */
};

printf("%d\n", marks[1][2]);   /* 55 */
02

Nested loops walk the table

The outer loop picks a row, the inner one walks its columns. To total each student you sum across the inner loop; to total each subject you swap the loops so the column is fixed and the row varies.

The elements sit in memory one row after another. Walking in row order therefore reads consecutive memory, which is why row-major loops run faster on large tables than column-major ones.

Swap the loops to change what you are totalling
/* Total per student: fix the row, walk the columns */
for (int s = 0; s < 3; s++) {
    int total = 0;
    for (int j = 0; j < 4; j++)
        total += marks[s][j];
    printf("Student %d total %d\n", s, total);
}

/* Total per subject: fix the column, walk the rows */
for (int j = 0; j < 4; j++) {
    int total = 0;
    for (int s = 0; s < 3; s++)
        total += marks[s][j];
    printf("Subject %d total %d\n", j, total);
}
03

Passing a 2D array

A function receiving a 2D array must be told the number of columns: void print_table(int t[][4], int rows). Without it, the compiler cannot work out where row 1 starts, because that calculation is row number times columns per row.

The number of rows may be left out because it is not needed for that arithmetic — you pass it separately, exactly as you pass the length of a one-dimensional array.

Try it yourself

Store marks for three students in four subjects, then print each student's average and each subject's highest mark.

Need a hint?

Student averages fix the row; subject highs fix the column. That is two differently-nested loops, not one.

Check the worked solution

Seeding the subject maximum from row 0 rather than from 0 is the same reasoning as Unit II's range function — a hardcoded 0 would be wrong the moment a subject had all-negative or all-small values. SUBJECTS appears in both the declaration and the parameter type, so the two can never drift apart.

#include <stdio.h>
#define STUDENTS 3
#define SUBJECTS 4

int main(void)
{
    int marks[STUDENTS][SUBJECTS] = {
        {72, 45, 91, 38},
        {66, 80, 55, 74},
        {90, 88, 79, 61}
    };

    for (int s = 0; s < STUDENTS; s++) {
        int total = 0;
        for (int j = 0; j < SUBJECTS; j++)
            total += marks[s][j];
        printf("Student %d average %.2f\n", s, (double) total / SUBJECTS);
    }

    for (int j = 0; j < SUBJECTS; j++) {
        int high = marks[0][j];
        for (int s = 1; s < STUDENTS; s++)
            if (marks[s][j] > high)
                high = marks[s][j];
        printf("Subject %d highest %d\n", j, high);
    }

    return 0;
}

Quick check

Why must a 2D array parameter specify the column count, as in int t[][4]?

Select an answer to check your thinking.

Why this lesson exists

Syllabus mapping

Multidimensional Arrays · Using for Loops for Sequential Access

Maps to course outcome CO5.