C Tutorial
C 2D Arrays
An array of arrays stores a table. Use two indexes: row, then column.
A table under one name
A one-dimensional array is a single row of values. A two-dimensional array is a row of rows: a table. Each inner row has the same length and the same element type. You still index from 0.
Write two sizes in two pairs of brackets: int grid[2][3]. The first size is the number of rows. The second is the number of columns. The cell at row r and column c isgrid[r][c]. Row first, then column. Mixing that order is the usual bug.
Declare int grid[2][3]
The braces nest the same way the table looks. The outer braces wrap the whole array. Each inner brace list is one row. This grid has two rows and three columns. Print one cell by writing both indexes.
Example
#include <stdio.h>
int main(void) {
int grid[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
printf("%d\n", grid[0][0]);
printf("%d\n", grid[1][2]);
return 0;
}grid[0][0] is 1, the first cell of the first row. grid[1][2] is 6, the last cell of the second row. There is no grid[2] and no grid[0][3]. Those indexes are off the end.
Walk the table with nested loops
The outer loop runs once per row. The inner loop runs once per column of that row. Print a space between cells and a newline after each row so the output looks like the table you stored.
Example
#include <stdio.h>
int main(void) {
int grid[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
for (int row = 0; row < 2; row++) {
for (int col = 0; col < 3; col++) {
printf("%d ", grid[row][col]);
}
printf("\n");
}
return 0;
}Compile this at /c/try. Change a value in the brace list and print again. The loop bounds stay 2 and 3 to match the declaration.
Map indexes to cells
| Expression | Row | Column | Value |
|---|---|---|---|
grid[0][0] | 0 | 0 | 1 |
grid[0][1] | 0 | 1 | 2 |
grid[0][2] | 0 | 2 | 3 |
grid[1][0] | 1 | 0 | 4 |
grid[1][1] | 1 | 1 | 5 |
grid[1][2] | 1 | 2 | 6 |
Assignment uses the same indexes: grid[0][1] = 20; overwrites 2. The array is not copied. That one integer changes.
Fill a grid in a loop
You do not have to list every cell in braces. This program writes a value into each slot, then prints the table. The stored number is a simple function of the indexes so you can see which cell is which.
Example
#include <stdio.h>
int main(void) {
int grid[2][3];
for (int row = 0; row < 2; row++) {
for (int col = 0; col < 3; col++) {
grid[row][col] = row * 10 + col;
}
}
for (int row = 0; row < 2; row++) {
for (int col = 0; col < 3; col++) {
printf("%d ", grid[row][col]);
}
printf("\n");
}
return 0;
}Without the first pair of loops, grid would hold leftover memory. Initialize every cell before you print it, either with nested braces or with nested assignment.
Stay inside both bounds
Valid rows are 0 through rows - 1. Valid columns are 0 throughcols - 1. The compiler will not stop a bad pair of indexes. The table cannot grow: if you need more rows, declare a larger array.
Next: group related values of different types with a struct.
Worked examples
The short listings above are there so you can see the grammar. The programs here use the same statements on quantities that already have units: a speed, a pH, a count of bases. They are classroom numbers. Air resistance is ignored. g is 9.81 m/s² unless a line says otherwise.
Open them in the C editor at /c/try. Change one measurement and check whether the result still has the right unit.
Maths
Determinant of a 2×2
For [[a, b], [c, d]] the determinant is ad − bc. Here 3×4 − 1×2 = 10. A zero determinant means the rows are linearly dependent: the parallelogram they span has no area.
Two indexes are row then column. m[0][1] is the first row, second column — b in the usual layout.
det = ad − bc
Example
#include <stdio.h>
int main(void) {
double m[2][2] = {{3.0, 1.0}, {2.0, 4.0}};
double det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
printf("det = %.1f\n", det);
return 0;
}Chemistry
Yields in a grid
A designed experiment often crosses one factor with another. Rows are reagents, columns are repeat runs. yield[1][1] is reagent B, second run: 0.65.
The table in the lab book is already a 2D array. The program is that table with indexes instead of a pencil.
Example
#include <stdio.h>
int main(void) {
double yield[2][3] = {
{0.81, 0.79, 0.84},
{0.62, 0.65, 0.60}
};
printf("reagent B, run 2: %.2f\n", yield[1][1]);
return 0;
}