README
Multi-Dimensional Arrays in C
Table of Contents
- β’Introduction
- β’What are Multi-Dimensional Arrays?
- β’Two-Dimensional Arrays
- β’Declaration and Initialization
- β’Accessing Elements
- β’Memory Layout
- β’Common Operations
- β’Three-Dimensional Arrays
- β’Passing to Functions
- β’Common Mistakes
- β’Best Practices
- β’Summary
Introduction
Multi-dimensional arrays extend the concept of arrays to store data in a tabular or matrix format. They are essential for representing grids, tables, matrices, images, and other structured data.
What are Multi-Dimensional Arrays?
A multi-dimensional array is an array of arrays. The most common type is the two-dimensional array (2D array), which can be visualized as a table with rows and columns.
Types of Multi-Dimensional Arrays
| Dimension | Description | Example Use Case |
|---|---|---|
| 1D | Linear list | Simple list of values |
| 2D | Table/Matrix | Spreadsheet, game board |
| 3D | Cube of data | 3D graphics, video frames |
| nD | Higher dimensions | Scientific simulations |
Visual Comparison
1D Array (List):
βββββ¬ββββ¬ββββ¬ββββ¬ββββ
β 1 β 2 β 3 β 4 β 5 β
βββββ΄ββββ΄ββββ΄ββββ΄ββββ
2D Array (Table/Matrix):
Col 0 Col 1 Col 2 Col 3
ββββββββ¬βββββββ¬βββββββ¬βββββββ
Row 0β 1 β 2 β 3 β 4 β
ββββββββΌβββββββΌβββββββΌβββββββ€
Row 1β 5 β 6 β 7 β 8 β
ββββββββΌβββββββΌβββββββΌβββββββ€
Row 2β 9 β 10 β 11 β 12 β
ββββββββ΄βββββββ΄βββββββ΄βββββββ
3D Array (Cube):
βββββββββββββββββββ
/β Layer 0 /β
/ β / β
/ β / β
βββββββββββββββββ β
β Layer 1 β β
β βββ¬ββ¬ββ β /
β βββΌββΌββ€ β /
β βββ΄ββ΄ββ β /
βββββββββββββββββ/
Two-Dimensional Arrays
Concept
A 2D array is organized as rows and columns, similar to a spreadsheet or matrix.
int matrix[3][4]; // 3 rows, 4 columns
Column
0 1 2 3
βββββ¬ββββ¬ββββ¬ββββ
Row 0 β β β β β
βββββΌββββΌββββΌββββ€
Row 1 β β β β β
βββββΌββββΌββββΌββββ€
Row 2 β β β β β
βββββ΄ββββ΄ββββ΄ββββ
Total elements = Rows Γ Columns = 3 Γ 4 = 12
Syntax
data_type array_name[rows][columns];
Examples
int matrix[3][4]; // 3 rows, 4 columns of integers
float grades[5][3]; // 5 students, 3 subjects
char board[8][8]; // 8x8 chess board
double pixels[1080][1920]; // HD screen pixels
Declaration and Initialization
Method 1: Declaration Only
int matrix[3][4]; // Uninitialized (contains garbage)
Method 2: Initialize with Values
int matrix[3][4] = {
{1, 2, 3, 4}, // Row 0
{5, 6, 7, 8}, // Row 1
{9, 10, 11, 12} // Row 2
};
Method 3: Partial Initialization
int matrix[3][4] = {
{1, 2}, // Row 0: {1, 2, 0, 0}
{5}, // Row 1: {5, 0, 0, 0}
{9, 10, 11} // Row 2: {9, 10, 11, 0}
};
// Remaining elements are 0
Method 4: All Zeros
int matrix[3][4] = {0}; // All 12 elements are 0
Method 5: Linear Initialization
int matrix[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// Fills row by row automatically
Method 6: Omit First Dimension
int matrix[][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// Compiler determines rows = 3
// Note: Second dimension (columns) MUST be specified!
Initialization Visualization
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
Memory Layout:
βββββ¬ββββ¬ββββ¬ββββ¬ββββ¬ββββ
β 1 β 2 β 3 β 4 β 5 β 6 β
βββββ΄ββββ΄ββββ΄ββββ΄ββββ΄ββββ
β β
Row 0 Row 1
Logical View:
Col 0 Col 1 Col 2
ββββββββ¬βββββββ¬βββββββ
Row 0β 1 β 2 β 3 β
ββββββββΌβββββββΌβββββββ€
Row 1β 4 β 5 β 6 β
ββββββββ΄βββββββ΄βββββββ
Accessing Elements
Syntax
array_name[row_index][column_index]
Reading Elements
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int element = matrix[1][2]; // Row 1, Column 2 β 7
int first = matrix[0][0]; // First element β 1
int last = matrix[2][3]; // Last element β 12
Writing Elements
matrix[0][0] = 100; // Change first element
matrix[1][2] = 77; // Change element at row 1, col 2
matrix[2][3] = 999; // Change last element
Index Ranges
For int arr[ROWS][COLS]:
- Valid row indices: 0 to ROWS-1
- Valid column indices: 0 to COLS-1
Element positions:
βββββββββββββββ¬ββββββββββββββββ¬ββββββββββββββββ
β arr[0][0] β arr[0][1] β ... arr[0][COLS-1] β
βββββββββββββββΌββββββββββββββββΌββββββββββββββββ€
β arr[1][0] β arr[1][1] β ... arr[1][COLS-1] β
βββββββββββββββΌββββββββββββββββΌββββββββββββββββ€
β ... β ... β ... β
βββββββββββββββΌββββββββββββββββΌββββββββββββββββ€
βarr[ROWS-1][0]βarr[ROWS-1][1]β...arr[ROWS-1][COLS-1]β
βββββββββββββββ΄ββββββββββββββββ΄ββββββββββββββββ
Memory Layout
Row-Major Order
In C, 2D arrays are stored in row-major order: all elements of row 0 first, then row 1, and so on.
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
Logical View: Memory (Row-Major):
[0][1][2] Address: 100 104 108 112 116 120
ββββ¬βββ¬βββ ββββββ¬βββββ¬βββββ¬βββββ¬βββββ¬βββββ
[0]β1 β2 β3 β β 1 β 2 β 3 β 4 β 5 β 6 β
ββββΌβββΌβββ€ β ββββββ΄βββββ΄βββββ΄βββββ΄βββββ΄βββββ
[1]β4 β5 β6 β ββββββRow 0ββββββββββββRow 1ββββββ
ββββ΄βββ΄βββ
Address Calculation
Address of arr[i][j] = Base + (i Γ COLS + j) Γ sizeof(element)
For arr[1][2] with base = 100, COLS = 3, sizeof(int) = 4:
Address = 100 + (1 Γ 3 + 2) Γ 4
= 100 + 5 Γ 4
= 100 + 20
= 120
Size Calculation
int matrix[3][4];
// Total size in bytes
size_t totalBytes = sizeof(matrix); // 3 Γ 4 Γ 4 = 48 bytes
// Size of one row
size_t rowSize = sizeof(matrix[0]); // 4 Γ 4 = 16 bytes
// Number of rows
size_t rows = sizeof(matrix) / sizeof(matrix[0]); // 3
// Number of columns
size_t cols = sizeof(matrix[0]) / sizeof(matrix[0][0]); // 4
Common Operations
1. Traversing (Printing) a 2D Array
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// Row by row traversal
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
2. Sum of All Elements
int sum = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
sum += matrix[i][j];
}
}
printf("Sum: %d\n", sum);
3. Row Sum and Column Sum
// Sum of each row
for (int i = 0; i < 3; i++) {
int rowSum = 0;
for (int j = 0; j < 4; j++) {
rowSum += matrix[i][j];
}
printf("Row %d sum: %d\n", i, rowSum);
}
// Sum of each column
for (int j = 0; j < 4; j++) {
int colSum = 0;
for (int i = 0; i < 3; i++) {
colSum += matrix[i][j];
}
printf("Column %d sum: %d\n", j, colSum);
}
4. Finding Maximum Element
int max = matrix[0][0];
int maxRow = 0, maxCol = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if (matrix[i][j] > max) {
max = matrix[i][j];
maxRow = i;
maxCol = j;
}
}
}
printf("Max: %d at [%d][%d]\n", max, maxRow, maxCol);
5. Matrix Transpose
int original[2][3] = {{1, 2, 3}, {4, 5, 6}};
int transposed[3][2];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
transposed[j][i] = original[i][j];
}
}
Original [2][3]: Transposed [3][2]:
βββββ¬ββββ¬ββββ βββββ¬ββββ
β 1 β 2 β 3 β β 1 β 4 β
βββββΌββββΌββββ€ β βββββΌββββ€
β 4 β 5 β 6 β β 2 β 5 β
βββββ΄ββββ΄ββββ βββββΌββββ€
β 3 β 6 β
βββββ΄ββββ
6. Matrix Addition
int A[2][2] = {{1, 2}, {3, 4}};
int B[2][2] = {{5, 6}, {7, 8}};
int C[2][2]; // Result
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
C[i][j] = A[i][j] + B[i][j];
}
}
// C = {{6, 8}, {10, 12}}
7. Matrix Multiplication
int A[2][3] = {{1, 2, 3}, {4, 5, 6}};
int B[3][2] = {{7, 8}, {9, 10}, {11, 12}};
int C[2][2] = {0}; // Result: [2Γ3] Γ [3Γ2] = [2Γ2]
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 3; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
Three-Dimensional Arrays
Concept
A 3D array can be visualized as multiple 2D arrays stacked together (like layers or pages).
int cube[2][3][4]; // 2 layers, each with 3 rows and 4 columns
Layer 0 (cube[0]): Layer 1 (cube[1]):
[0][1][2][3] [0][1][2][3]
ββββ¬βββ¬βββ¬βββ ββββ¬βββ¬βββ¬βββ
[0] β β β β β [0] β β β β β
ββββΌβββΌβββΌβββ€ ββββΌβββΌβββΌβββ€
[1] β β β β β [1] β β β β β
ββββΌβββΌβββΌβββ€ ββββΌβββΌβββΌβββ€
[2] β β β β β [2] β β β β β
ββββ΄βββ΄βββ΄βββ ββββ΄βββ΄βββ΄βββ
Total elements = 2 Γ 3 Γ 4 = 24
Declaration and Initialization
int cube[2][3][4] = {
// Layer 0
{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
},
// Layer 1
{
{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24}
}
};
Accessing Elements
int value = cube[1][2][3]; // Layer 1, Row 2, Column 3 β 24
cube[0][0][0] = 100; // First element
cube[1][2][3] = 999; // Last element
Traversing 3D Array
for (int layer = 0; layer < 2; layer++) {
printf("Layer %d:\n", layer);
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 4; col++) {
printf("%3d ", cube[layer][row][col]);
}
printf("\n");
}
printf("\n");
}
Passing to Functions
Important Rule
When passing multi-dimensional arrays to functions, all dimensions except the first must be specified.
Passing 2D Array
// Method 1: Specify all dimensions
void printMatrix(int arr[3][4], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
// Method 2: Omit first dimension
void printMatrix(int arr[][4], int rows) {
// Same as above
}
// Method 3: Pointer notation
void printMatrix(int (*arr)[4], int rows) {
// Same as above
}
// Usage
int matrix[3][4] = {...};
printMatrix(matrix, 3);
Why Second Dimension is Required
The compiler needs to know the column size to calculate element addresses:
Address of arr[i][j] = Base + (i Γ COLS + j) Γ sizeof(element)
β
COLS must be known!
Variable Length Arrays (C99+)
void printMatrix(int rows, int cols, int arr[rows][cols]) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
Common Mistakes
1. Wrong Order of Indices
int matrix[3][4]; // 3 rows, 4 columns
// WRONG: Thinking [column][row]
matrix[4][3] = 10; // Undefined behavior!
// CORRECT: [row][column]
matrix[2][3] = 10;
2. Missing Inner Braces
// Can work but confusing
int arr[2][3] = {1, 2, 3, 4, 5, 6};
// BETTER: Use inner braces
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
3. Omitting Required Dimension
// WRONG: Second dimension missing
void func(int arr[][]) {...} // Error!
// CORRECT: Specify second dimension
void func(int arr[][4]) {...}
4. Out of Bounds Access
int matrix[3][4];
// WRONG: Accessing beyond limits
matrix[3][0] = 10; // Row 3 doesn't exist!
matrix[0][4] = 10; // Column 4 doesn't exist!
5. Confusing Size Calculations
void func(int arr[][4]) {
// WRONG: sizeof(arr) gives pointer size, not array size
int size = sizeof(arr); // Size of pointer!
}
Best Practices
1. Use Named Constants for Dimensions
#define ROWS 3
#define COLS 4
int matrix[ROWS][COLS];
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
// ...
}
}
2. Initialize Arrays
int matrix[3][4] = {0}; // All zeros
3. Pass Dimensions to Functions
void processMatrix(int arr[][COLS], int rows, int cols) {
// Use rows and cols for bounds checking
}
4. Check Bounds Before Access
if (row >= 0 && row < ROWS && col >= 0 && col < COLS) {
matrix[row][col] = value;
}
5. Use Meaningful Variable Names
// Instead of i and j
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
matrix[row][col] = row * COLS + col;
}
}
Summary
Quick Reference
| Concept | Syntax/Example |
|---|---|
| Declaration | int arr[3][4]; |
| Initialization | int arr[2][3] = {{1,2,3}, {4,5,6}}; |
| Access element | arr[row][col] |
| Total elements | rows Γ columns |
| Memory | Row-major order (row by row) |
| Pass to function | func(int arr[][COLS], int rows) |
Key Points
β 2D arrays are arrays of arrays
β Stored in row-major order in memory
β First index = row, Second index = column
β Valid indices: [0 to rows-1][0 to cols-1]
β When passing to functions, specify all dimensions except first
β Use nested loops to traverse (outer = rows, inner = columns)
Dimension Summary
1D: arr[SIZE] - Single index
2D: arr[ROWS][COLS] - Two indices (row, col)
3D: arr[D1][D2][D3] - Three indices (layer, row, col)
Next Steps
After mastering multi-dimensional arrays:
- β’Learn about Passing Arrays to Functions
- β’Study Arrays and Pointers relationship
- β’Explore Dynamic 2D Arrays with malloc
- β’Practice matrix operations
"Think of 2D arrays as a table: rows go across, columns go down."