Row-major layout, passing them to functions, dynamic allocation, matrix & image examples. Follows the basic arrays lesson.
int a[3][4] is really 12 contiguous ints. "2D" is just how you think about it.
// 3 rows Γ 4 columns int m[3][4] = { { 1, 2, 3, 4}, { 5, 6, 7, 8}, { 9, 10, 11, 12} }; printf("%d\n", m[1][2]); // β 7 (row 1, column 2, 0-indexed)
// 2 layers Γ 3 rows Γ 4 columns int cube[2][3][4]; for (int l = 0; l < 2; l++) for (int i = 0; i < 3; i++) for (int j = 0; j < 4; j++) cube[l][i][j] = l * 100 + i * 10 + j;
int m[3][4] = {0}; zero-fills. int m[][4] = {{1,2,3,4},{5,6,7,8}}; β only the outer size may be omitted; column counts are required.int m[3][4]; sizeof(m) // 48 (3 * 4 * 4 bytes) sizeof(m[0]) // 16 (one row = 4 * 4 bytes) sizeof(m[0][0]) // 4 (one int) // rows = sizeof(m) / sizeof(m[0]) // cols = sizeof(m[0]) / sizeof(m[0][0])
int *p = (int *)m; p[i*COLS + j]
// Walk a 2D array as if it were 1D int m[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int *p = (int *)m; for (int k = 0; k < 12; k++) printf("%d ", p[k]); // β 1 2 3 4 5 6 7 8 9 10 11 12
// column count is required; row count can be omitted void print_34(int m[][4], int rows) { for (int i = 0; i < rows; i++) for (int j = 0; j < 4; j++) printf("%d ", m[i][j]); } int a[3][4]; print_34(a, 3);
// Declare rows/cols first, then take the VLA array void print_any(int rows, int cols, int m[rows][cols]) { for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) printf("%d ", m[i][j]); } int a[3][4], b[2][5]; print_any(3, 4, a); print_any(2, 5, b);
m[i][j] syntax. Con: requires C99+; old MSVC doesn't support VLAs.// "Flatten" into 1D; compute the index yourself. void print_flat(int *m, int rows, int cols) { for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) printf("%d ", m[i * cols + j]); } int a[3][4]; print_flat((int *)a, 3, 4);
m[i][j] syntax.// Pass an array of row pointers void print_pp(int **m, int rows, int cols) { for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) printf("%d ", m[i][j]); } // caller must build an array of row pointers int row0[] = {1,2,3}; int row1[] = {4,5,6}; int *rows[] = {row0, row1}; print_pp(rows, 2, 3);
int a[3][4] to int ** does NOT work. Their memory representations differ: one is a block of ints, the other is an array of pointers. This is the biggest source of confusion with multi-dim arrays.#include <stdio.h> #include <stdlib.h> int main(void) { int rows = 3, cols = 4; // allocate all elements in one block int *m = malloc(sizeof(int) * rows * cols); if (!m) return 1; // manual indexing: m[i*cols + j] for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) m[i * cols + j] = i * 10 + j; free(m); return 0; }
// Contiguous block AND 2D indexing int (*m)[cols] = malloc(sizeof(int[rows][cols])); m[1][2] = 42; // normal subscripts work free(m);
int **m = malloc(sizeof(int *) * rows); // row pointer array for (int i = 0; i < rows; i++) m[i] = malloc(sizeof(int) * cols); // one row each m[1][2] = 42; // m[i][j] syntax works // free in reverse order for (int i = 0; i < rows; i++) free(m[i]); free(m);
C[i][j] = Ξ£ A[i][l] * B[l][j].#include <stdio.h> #define M 2 #define K 3 #define N 2 void matmul(int A[M][K], int B[K][N], int C[M][N]) { for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) { int sum = 0; for (int l = 0; l < K; l++) sum += A[i][l] * B[l][j]; C[i][j] = sum; } } int main(void) { int A[M][K] = {{1,2,3},{4,5,6}}; int B[K][N] = {{7,8},{9,10},{11,12}}; int C[M][N]; matmul(A, B, C); for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) printf("%4d", C[i][j]); putchar('\n'); } // expected: // 58 64 // 139 154 }
ilj order (accumulating over l in the innermost loop) accesses B row-wise and can be significantly faster on large matrices thanks to row-major caching.#include <stdio.h> #define W 6 #define H 4 void flip_horizontal(unsigned char img[H][W]) { for (int i = 0; i < H; i++) for (int j = 0; j < W / 2; j++) { unsigned char t = img[i][j]; img[i][j] = img[i][W - 1 - j]; img[i][W - 1 - j] = t; } } int main(void) { unsigned char img[H][W] = { {10,20,30,40,50,60}, {11,21,31,41,51,61}, {12,22,32,42,52,62}, {13,23,33,43,53,63}, }; flip_horizontal(img); for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) printf("%3d ", img[i][j]); putchar('\n'); } }
unsigned char img[H][W][3]. For a vertical flip, swap whole rows with memcpy.int B[4][3] of int A[3][4].int table[9][9] with (i+1)*(j+1) and print it.memcpy to swap entire rows at once.int trace(int n, int m[n][n]) (VLA parameter) returning the sum of diagonal entries.int(*)[N]