ภาพรวม Multidimensional Arrays
Multidimensional Array (อาร์เรย์หลายมิติ) คืออาร์เรย์ที่มีมิติมากกว่าหนึ่งมิติ มิติที่พบบ่อยที่สุดคือ 2 มิติ (2D Array) ที่จัดเก็บข้อมูลในรูปแบบตาราง แถว (Rows) และ คอลัมน์ (Columns)
การประกาศและเริ่มต้นค่า
Syntax
data_type array_name[size1][size2]...[sizeN];
ตัวอย่าง 2D Array
// ประกาศและกำหนดค่าเริ่มต้น
int matrix[3][4] = {
{1, 2, 3, 4}, // Row 0
{5, 6, 7, 8}, // Row 1
{9, 10, 11, 12} // Row 2
};
// หรือแบบย่อ (C99)
int matrix[][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}; // จำนวน Row ไม่ต้องระบุ
การเข้าถึงข้อมูล
// เข้าถึงแถว i คอลัมน์ j (0-based index) value = array[i][j]; // ตัวอย่าง matrix[0][0] = 1; // แถวแรก คอลัมน์แรก matrix[2][3] = 12; // แถวสุดท้าย คอลัมน์สุดท้าย
การจัดเก็บในหน่วยความจำ (Memory Layout)
C ใช้ Row-Major Order - เก็บข้อมูลแถวต่อแถวติดกัน
Row-Major Order
Array[3][4] ในหน่วยความจำ: Row 0: [0][0] [0][1] [0][2] [0][3] Row 1: [1][0] [1][1] [1][2] [1][3] Row 2: [2][0] [2][1] [2][2] [2][3] Address of A[i][j] = Base_Address + (i * COLS + j) * sizeof(element)
Column-Major Order (Fortran, MATLAB)
เก็บคอลัมน์ต่อคอลัมน์: Col 0: [0][0] [1][0] [2][0] Col 1: [0][1] [1][1] [2][1] ... Address of A[i][j] = Base_Address + (j * ROWS + i) * sizeof(element)
ตัวอย่างโค้ด C สมบูรณ์
#include <stdio.h>
#define ROWS 3
#define COLS 4
void printMatrix(int matrix[ROWS][COLS]) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("matrix[%d][%d] = %d\t", i, j, matrix[i][j]);
}
printf("\n");
}
}
void printMemoryLayout(int matrix[ROWS][COLS]) {
printf("\nMemory Layout (Row-Major):\n");
int* ptr = &matrix[0][0];
for (int i = 0; i < ROWS * COLS; i++) {
printf("Address %p: %d\n", (void*)(ptr + i), *(ptr + i));
}
}
int main() {
// 1. การประกาศและเริ่มต้น
int matrix[ROWS][COLS] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
printf("=== 2D Array Example ===\n");
printMatrix(matrix);
// 2. แสดง Memory Layout
printMemoryLayout(matrix);
// 3. การคำนวณ Address
printf("\nAddress Calculation:\n");
int* base = &matrix[0][0];
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
int* addr = base + (i * COLS + j);
printf("matrix[%d][%d] at %p (offset %ld)\n", i, j, (void*)addr, (long)(addr - base));
}
}
// 4. 3D Array Example
printf("\n=== 3D Array ===\n");
int cube[2][3][4] = {
{ {1,2,3,4}, {5,6,7,8}, {9,10,11,12} },
{ {13,14,15,16}, {17,18,19,20}, {21,22,23,24} }
};
printf("cube[1][2][3] = %d\n", cube[1][2][3]); // 24
printf("Total elements: %zu\n", sizeof(cube) / sizeof(int));
return 0;
}
ผลลัพธ์ตัวอย่าง
=== 2D Array Example === matrix[0][0] = 1 matrix[0][1] = 2 matrix[0][2] = 3 matrix[0][3] = 4 matrix[1][0] = 5 matrix[1][1] = 6 matrix[1][2] = 7 matrix[1][3] = 8 matrix[2][0] = 9 matrix[2][1] = 10 matrix[2][2] = 11 matrix[2][3] = 12 Memory Layout (Row-Major): Address 0x7ffe...: 1 Address 0x7ffe...: 2 Address 0x7ffe...: 3 Address 0x7ffe...: 4 Address 0x7ffe...: 5 Address 0x7ffe...: 6 ... cube[1][2][3] = 24 Total elements: 24
การผ่าน Array ให้ Function
// วิธี 1: ระบุขนาด Column (ต้องคงที่)
void func1(int arr[][4], int rows);
// วิธี 2: Pointer to Array
void func2(int (*arr)[4], int rows);
// วิธี 3: Flatten เป็น 1D (ยืดหยุ่นกว่า)
void func3(int* arr, int rows, int cols) {
// เข้าถึง: arr[i * cols + j]
}
// วิธี 4: Variable Length Array (C99)
void func4(int rows, int cols, int arr[rows][cols]);
การจัดสรรหน่วยความจำแบบ Dynamic
วิธี 1: Array of Pointers (Jagged Array)
int** create2D(int rows, int cols) {
int** arr = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
arr[i] = malloc(cols * sizeof(int));
}
return arr;
}
// Free
void free2D(int** arr, int rows) {
for (int i = 0; i < rows; i++) free(arr[i]);
free(arr);
}
วิธี 2: Single Block (Contiguous Memory)
int* create2DContiguous(int rows, int cols) {
return malloc(rows * cols * sizeof(int));
}
// Access: arr[i * cols + j]
// Free: free(arr); // แค่ครั้งเดียว
ตัวอย่างการใช้งาน: Matrix Operations
// Matrix Addition
void addMatrix(int a[][COLS], int b[][COLS], int result[][COLS], int rows) {
for (int i = 0; i < rows; i++)
for (int j = 0; j < COLS; j++)
result[i][j] = a[i][j] + b[i][j];
}
// Matrix Multiplication
void mulMatrix(int a[][COLS], int b[][COLS], int result[][COLS], int rowsA, int colsA, int colsB) {
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
result[i][j] = 0;
for (int k = 0; k < colsA; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
}
Best Practices
- ใช้
#defineหรือconstสำหรับขนาด Array - เลือก Row-Major สำหรับ C/C++ (Cache Friendly)
- หลีกเลี่ยงการเข้าถึง Column-Major Pattern ใน Row-Major Array (Cache Miss)
- ใช้ Contiguous Allocation สำหรับ Performance ที่ดีกว่า
- ตรวจสอบ Bounds เสมอ เพื่อป้องกัน Buffer Overflow
ข้อจำกัด
- ขนาดต้องทราบที่ Compile Time (สำหรับ Static Array)
- Stack Overflow ถ้าประกาศ Array ใหญ่ใน Function
- ไม่รองรับ Jagged Array แบบ Native (ต้องใช้ Pointer)