Banyak data nyata secara alami berbentuk dua dimensi atau lebih: matriks dalam aljabar linier, papan catur 8×8, piksel gambar 320×240, atau data penjualan toko × bulan. C mendukung array multi-dimensi dengan sintaks tipe nama[d1][d2]...[dn]. Memori tetap satu dimensi—array 2D sebenarnya disimpan sebagai row-major order (baris demi baris)—tetapi compiler menghitung offset otomatis untuk kita. Pada chapter ini kita akan menelusuri deklarasi array 2D, akses elemen, dan ekstensi ke array 3D.
Deklarasi dan Akses Array 2D #
Bentuk umum deklarasi array 2D adalah tipe nama[baris][kolom]. Contoh int m[3][4] berarti 3 baris × 4 kolom, total 12 elemen int (48 byte pada sizeof(int) = 4). Akses elemen menggunakan dua indeks: m[baris][kolom]. Indeks pertama menentukan baris, indeks kedua menentukan kolom—keduanya dimulai dari 0.
Visualisasi Konsep #
Diagram berikut memperlihatkan bagaimana matriks 3×4 disimpan dalam memori dengan row-major order (baris demi baris):
Pada diagram di atas, matriks 3×4 tampak secara logis sebagai tiga baris × empat kolom, tetapi di memori semua elemen disimpan dalam satu blok 48 byte berurutan mengikuti row-major order: baris 0 dahulu (1, 2, 3, 4), lalu baris 1 (5, 6, 7, 8), lalu baris 2 (9, 10, 11, 12). Compiler menghitung alamat elemen m[i][j] melalui rumus &m[0][0] + (i * jumlah_kolom + j) * sizeof(int). Inilah sebabnya deklarasi int m[3][4] wajib menyertakan ukuran kolom—compiler membutuhkan jumlah_kolom untuk menghitung offset.
Contoh Matriks 3x4 #
Contoh berikut mendeklarasikan matriks 3×4, mengakses satu elemen, mencetak seluruh matriks dengan nested loop, menghitung total elemen, dan menampilkan dimensi melalui sizeof.
#include <stdio.h>
int main(void) {
/* Array 2D berukuran 3 baris x 4 kolom */
int matriks[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
/* Akses elemen baris 1 kolom 2 (zero-based) */
printf("matriks[1][2] = %d\n", matriks[1][2]);
/* Cetak seluruh elemen dengan nested loop */
printf("Isi matriks:\n");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%4d", matriks[i][j]);
}
printf("\n");
}
/* Hitung total seluruh elemen */
int total = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
total += matriks[i][j];
}
}
printf("Total: %d\n", total);
/* sizeof pada array 2D */
printf("sizeof(matriks) = %zu\n", sizeof(matriks));
printf("Jumlah baris: %zu\n", sizeof(matriks) / sizeof(matriks[0]));
printf("Jumlah kolom: %zu\n", sizeof(matriks[0]) / sizeof(matriks[0][0]));
return 0;
}Output yang Dihasilkan:
matriks[1][2] = 7
Isi matriks:
1 2 3 4
5 6 7 8
9 10 11 12
Total: 78
sizeof(matriks) = 48
Jumlah baris: 3
Jumlah kolom: 4Mari kita telaah baris-baris kode di atas:
- Baris 4 (
int matriks[3][4] = {...};): deklarasi array 2D berukuran 3 baris × 4 kolom. Setiap inner brace{...}merepresentasikan satu baris. Total 12 elemen, masing-masing 4 byte, total 48 byte. - Baris 11 (
printf("matriks[1][2] = %d\n", matriks[1][2]);): akses elemen pada baris indeks1, kolom indeks2—yaitu7. Indeks0adalah baris pertama, indeks1adalah baris kedua. - Baris 14-19 (
for i, for j): nested loop. Loop luarimengiterasi baris (0..2), loop dalamjmengiterasi kolom (0..3). Format%4dmembuat setiap angka menempati lebar minimal 4 karakter agar output rapi. - Baris 22-26 (
total += matriks[i][j];): akumulasi seluruh elemen. Pola identik dengan array 1D, hanya saja sekarang ada dua indeks. - Baris 29 (
sizeof(matriks)= 48): ukuran total array 2D. 12 elemen × 4 byte = 48 byte. - Baris 30 (
sizeof(matriks) / sizeof(matriks[0])= 3):matriks[0]adalah baris pertama, yang tipenya adalahint[4](16 byte). 48 / 16 = 3, yaitu jumlah baris. - Baris 31 (
sizeof(matriks[0]) / sizeof(matriks[0][0])= 4):matriks[0][0]bertipeint(4 byte). 16 / 4 = 4, yaitu jumlah kolom. Idiom ini bekerja rekursif untuk dimensi tambahan.
Trace Matriks dan Array 3D #
Contoh berikut memperlihatkan dua konsep: menghitung trace matriks (jumlah elemen diagonal utama) dan mendeklarasikan array 3D (dua buah matriks 2×3).
#include <stdio.h>
int main(void) {
/* Matriks 3x3 dengan inisialisasi langsung */
int A[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
/* Hitung trace = jumlah diagonal utama */
int trace = 0;
for (int i = 0; i < 3; i++) {
trace += A[i][i];
}
printf("Trace A = %d\n", trace);
/* Array 3D: dua buah matriks 2x3 */
int kubus[2][2][3] = {
{{1, 2, 3}, {4, 5, 6}},
{{7, 8, 9}, {10, 11, 12}}
};
printf("Layer 0:\n");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%3d", kubus[0][i][j]);
}
printf("\n");
}
printf("Layer 1:\n");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%3d", kubus[1][i][j]);
}
printf("\n");
}
return 0;
}Output yang Dihasilkan:
Trace A = 15
Layer 0:
1 2 3
4 5 6
Layer 1:
7 8 9
10 11 12Pada contoh di atas, trace matriks A adalah A[0][0] + A[1][1] + A[2][2] = 1 + 5 + 9 = 15. Pola A[i][i] mengakses elemen diagonal utama—baris dan kolom memiliki indeks yang sama. Array 3D kubus berukuran 2 × 2 × 3 = 12 elemen, terbagi menjadi 2 layer matriks 2×3. Mengakses elemen menggunakan tiga indeks kubus[layer][baris][kolom]. Pola nested loop dengan tiga level bisa mengiterasi seluruh elemen array 3D.