Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Multidimensional Arrays ในภาษา C

ภาพรวม 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)