在 C 語言中,**數組名作為函數參數時會退化為指向首元素的指針**。函數實際接收的是地址,因此可以在函數內部修改原數組內容。這屬於「模擬引用傳遞」或稱「地址傳遞」。
// 形式 1:數組語法(最直觀,推薦文檔用)
void func1(int arr[], int n);
// 形式 2:指針語法(本質相同)
void func2(int *arr, int n);
// 形式 3:帶長度的數組語法(C99 VLA,長度僅作文檔/優化提示)
void func3(int arr[10], int n); // 長度 10 被編譯器忽略,等同於 int *arr
#include <stdio.h>
// 修改數組內容
void modifyArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
arr[i] *= 2; // 直接修改原數組
}
}
// 只讀數組(建議加 const)
void printArray(const int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int scores[5] = {10, 20, 30, 40, 50};
int len = sizeof(scores) / sizeof(scores[0]);
printf("原數組: ");
printArray(scores, len);
modifyArray(scores, len); // 傳遞數組名即首地址
printf("修改後: ");
printArray(scores, len); // 原數組已被修改
return 0;
}
二維數組退化為「指向一維數組的指針」,**必須指定第二維長度**(列數):
// 正確:第二維固定為 4
void processMatrix(int matrix[][4], int rows);
// 等價指針寫法
void processMatrix(int (*matrix)[4], int rows);
// 調用
int data[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
processMatrix(data, 3);
int **matrix = malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
matrix[i] = malloc(cols * sizeof(int));
}
// 函數參數需聲明為 int **
void processDynamicMatrix(int **matrix, int rows, int cols);
| 陷阱 | 後果 | 解決方案 |
|---|---|---|
在函數內用 sizeof(arr) 求長度 | 得到指針大小(4/8 字節),而非數組大小 | **必須額外傳遞長度參數**,或結構體封裝 |
嘗試在函數內修改指針本身(如 arr = newArr) | 只修改局部副本,不影響調用者 | 若需修改指針指向,傳遞 int **arr(二級指針) |
| 數組越界訪問 | 未定義行為,難以調試 | 嚴格檢查索引,使用靜態分析工具 |
| 混淆「數組指針」與「指針數組」 | 編譯錯誤或運行時崩潰 | 牢記:int (*p)[N] 是數組指針,int *p[N] 是指針數組 |
typedef struct {
int *data;
size_t size;
size_t capacity;
} IntArray;
void initArray(IntArray *arr, size_t capacity) {
arr->data = malloc(capacity * sizeof(int));
arr->size = 0;
arr->capacity = capacity;
}
void pushBack(IntArray *arr, int value) {
if (arr->size >= arr->capacity) {
arr->capacity *= 2;
arr->data = realloc(arr->data, arr->capacity * sizeof(int));
}
arr->data[arr->size++] = value;
}
// 使用時自帶長度信息,安全且直觀
int **。const 表達只讀意圖,啟用編譯器優化與檢查。