C 語言教學:將陣列作為函式參數傳遞的完整指南(含一維與多維範例)

1. 前言

在 C 語言中將陣列作為參數傳遞的原因

在使用 C 語言編寫程式時,經常會需要在其他函式中使用陣列。例如,對資料集進行批次處理、大量資料的搜尋或排序等操作,若將陣列交由其他函式處理,能提高程式碼的重複利用率。

透過將陣列作為參數傳遞,可以讓程式碼模組化,將特定功能分離至各自的函式。這樣不僅能讓每個函式獨立進行測試與除錯,還能在多位開發者同時協作時提升效率。

本文將以淺顯易懂的方式,為初學者解說在 C 語言中如何將陣列作為參數傳遞及其注意事項。內容涵蓋從一維陣列到多維陣列,並結合實際程式碼範例,提供可實踐的知識。

目標讀者

本文的目標對象包括剛開始學習 C 語言的初學者,以及已掌握基礎用法的中階開發者。透過本文,不僅能學到陣列與函式的基礎知識,還能深入了解陣列的記憶體管理與指標使用,進而更有效率地構建程式。

2. 陣列與指標的基礎知識

陣列名稱與指標的關係

在 C 語言中,陣列是一段連續的記憶體區域,而陣列名稱本身具有指向該陣列起始位址的特殊角色。例如,宣告 int array[5]; 時,array 代表陣列起始位址(&array[0])。因此,在將陣列傳遞給函式時,只需直接使用陣列名稱,即可將整個陣列的起始位址傳遞過去。

理解這個關係非常重要,因為在 C 語言中,陣列名稱與指標有著密切的關聯,尤其是在理解指標運算時更是不可或缺。

陣列名稱與指標的差異

雖然陣列與指標有共通之處,但也存在幾個重要差異。例如,陣列的大小是固定的,而指標的大小可變,並且可以指向其他記憶體區域。此外,陣列在記憶體中是連續配置的,但指標不一定指向連續的記憶體空間。

以下的程式碼範例可以幫助更清楚地理解陣列與指標的關係:

#include <stdio.h>

void printArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
}

int main() {
    int array[5] = {1, 2, 3, 4, 5};
    printArray(array, 5);  // 傳遞陣列起始位址
    return 0;
}

在這段程式中,printArray 函式接收陣列的起始位址,並依序輸出陣列的每個元素。

侍エンジニア塾

3. 將一維陣列作為函式參數傳遞的方法

傳遞陣列起始位址的基本步驟

在 C 語言中,將陣列的起始位址傳給函式,就能在函式內操作陣列元素。這並不是將整個陣列複製傳遞,而只是傳遞記憶體的起始位址,因此效率高且記憶體消耗少。

#include <stdio.h>

void modifyArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // 將陣列元素乘以 2
    }
}

int main() {
    int array[5] = {1, 2, 3, 4, 5};
    modifyArray(array, 5);
    for (int i = 0; i < 5; i++) {
        printf("%d ", array[i]);
    }
    return 0;
}

在這段程式中,modifyArray 函式會將陣列元素乘以 2。由於傳遞的是 array 的起始位址,因此函式內可直接修改原陣列的內容。

傳遞陣列元素數量的方法

將陣列傳遞給函式時,必須同時傳遞陣列的大小。C 語言中沒有直接取得陣列長度的方法,因此必須由程式設計師手動傳遞。在上述範例中,size 參數就是用來在函式內取得陣列長度的。

4. 將多維陣列作為函式參數傳遞的方法

傳遞二維陣列時的注意事項

在將多維陣列傳遞給函式時,C 語言允許省略列數,但不能省略欄數。因此,在將二維陣列作為函式參數時,必須指定欄數。

#include <stdio.h>

void print2DArray(int arr[][3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int array[2][3] = {{1, 2, 3}, {4, 5, 6}};
    print2DArray(array, 2);
    return 0;
}

在這裡,二維陣列的欄數 3 已在函式參數中明確指定。這樣可以確保函式正確存取陣列的每個元素。

可變長陣列的運用(C99 之後)

自 C99 起,引入了可變長陣列(VLA),允許在函式參數中靈活指定陣列的大小。

#include <stdio.h>

void printFlexibleArray(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");
    }
}

int main() {
    int array[2][3] = {{1, 2, 3}, {4, 5, 6}};
    printFlexibleArray(2, 3, array);
    return 0;
}

使用可變長陣列可以靈活變更列數與欄數,使在函式內處理多維陣列更加方便。

5. 將陣列作為參數傳遞時的注意事項

陣列大小管理的重要性

將陣列傳給函式時,如果大小指定錯誤,可能會造成記憶體浪費或緩衝區溢位。因此,必須謹慎管理陣列大小,並在迴圈條件中確保不超過陣列界限。

動態陣列與記憶體管理

當需要動態配置記憶體時,可使用 mallocfree 在堆積(heap)區域分配與釋放記憶體。在函式中處理動態陣列時,必須避免遺漏釋放記憶體以防止記憶體洩漏。

函式內對陣列的修改與副作用

將陣列作為參數傳遞時,函式內的修改會影響到函式外的原始陣列。如果不希望產生外部影響,可以先建立陣列副本再進行操作,或設計成不會改變外部資料。

6. 常見問題 (FAQ)

如何取得陣列大小?

在 C 語言中,無法在函式內直接取得陣列大小,因此必須將陣列大小作為參數傳入。例如:void myFunction(int *arr, int size) 是常見的用法。

在定義陣列的地方(如 main 函式內),可以用 sizeof(array) / sizeof(array[0]) 來計算陣列大小。以下為範例:

#include <stdio.h>

void printArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
}

int main() {
    int array[] = {1, 2, 3, 4, 5};
    int size = sizeof(array) / sizeof(array[0]);  // 計算陣列大小
    printArray(array, size);
    return 0;
}

在這段程式中,sizeof(array) / sizeof(array[0]) 計算出元素數量,並將其作為參數傳入函式。

關於動態陣列的疑問

動態陣列適用於需要節省記憶體或事先不確定大小的情況。建立動態陣列時,可用 malloccalloc 分配堆積記憶體,並在使用結束後用 free 釋放。

#include <stdio.h>
#include <stdlib.h>

void fillArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        arr[i] = i * 2;  // 將值賦給每個元素
    }
}

int main() {
    int size = 5;
    int *array = (int *)malloc(size * sizeof(int));  // 動態配置記憶體
    if (array == NULL) {
        printf("記憶體配置失敗。\n");
        return 1;
    }
    fillArray(array, size);
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]);
    }
    free(array);  // 釋放記憶體
    return 0;
}

在此範例中,使用 malloc 配置記憶體,並在函式中操作陣列內容,最後用 free 釋放,避免記憶體洩漏。

應該使用陣列還是指標?

陣列與指標密切相關,但應依使用目的來選擇。若資料是固定長度且大小已知,適合使用陣列;若需要動態記憶體操作或處理可變長資料,則適合用指標。

在處理大型資料結構或可變長資料時,使用指標動態管理記憶體會更有效率。同時,指標在記憶體操作上比陣列更具彈性,因此要發揮 C 語言特性,理解指標是不可或缺的。

7. 總結

將陣列作為參數傳遞時的重點回顧

本文介紹了在 C 語言中,如何將陣列作為函式參數傳遞,涵蓋從一維到多維陣列的基礎知識與實作範例。將陣列作為參數傳遞能讓程式碼模組化並提升重複利用率,但在處理多維或動態陣列時,需對指標與記憶體管理有充分理解。

正確管理陣列大小,以及在使用動態記憶體時務必釋放資源,是確保程式品質與效能的關鍵。掌握這些原則,可以讓 C 語言程式更加穩定且高效。