C 採呼叫傳值,實參值複製給形參。若需在函數內修改陣列內容,必須傳遞陣列首元素位址(指標),在相同記憶體區間操作。
無論實參/形參,指向陣列(一維/多維)的指標參數有四類組合:
| 情況 | 實際參數 | 形式參數 | 說明 |
|---|---|---|---|
| 1 | 陣列名 | 指標變數 | 最常用:func(arr) → void func(int *p) |
| 2 | 指標變數 | 指標變數 | 指標直接傳遞 |
| 3 | 陣列名 | 固定大小陣列參數 | void func(int p[10]) 實際退化為指標 |
| 4 | 指標變數 | 固定大小陣列參數 | 同上 |
核心:函數參數宣告為int p[]或int p[10]等價於int *p,編譯器視為指標,不檢查大小。
二維陣列記憶體按列主序連續儲存(Row-major)。
int a[3][4]; // 3 列 4 行
int *ptr = a[0]; // ptr 指向首元素 a[0][0]
記憶體佈局:
a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] ... a[2][3]
ptr[0] ptr[1] ptr[2] ptr[3] ptr[4] ptr[5] ... ptr[11]
ptr[i] 對應 a[i/4][i%4](每列 4 元素)i / 4,行索引 = i % 4
#include
main() {
int a[3][4], *ptr, i, j, max, maxi, maxj;
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
scanf("%d", &a[i][j]);
ptr = a[0]; // 傳首元素位址
max_arr(ptr, &max, &maxi, 12); // 12 = 3*4 總元素數
maxj = maxi % 4; // 行索引
maxi = maxi / 4; // 列索引
printf("max=%d, maxi=%d, maxj=%d", max, maxi, maxj);
}
int max_arr(int *b, int *p1, int *p2, int n) {
int i;
*p1 = b[0]; // 最大值初始為首元素
*p2 = 0; // 位置初始為 0
for (i = 1; i < n; i++)
if (b[i] > *p1) {
*p1 = b[i];
*p2 = i;
}
}
執行流程:將二維陣列視為一維連續空間,單一迴圈掃描 12 個元素找最大值與一維索引,主程式再轉換為二維列行索引。
char str[20];
gets(str);
printf("%s\n", str); // str 為 char*,符合 %s 期望
char str[20], *p = str; // p 指向 str 首位址
gets(str);
printf("%s\n", p); // 以指標輸出字串
printf("%s")、puts、strlen 等),只能逐字元處理
#include
main() {
char str[10], *p = str;
int i;
scanf("%s", str); // 輸入超過 10 字元(無 \0 空間)
for (i = 0; i < 10; i++)
printf("%c", *p++); // 正確:逐字元輸出
printf("\n");
p = str;
printf("%s", p); // 錯誤:無 \0,繼續讀取記憶體直到遇 0
puts(str); // 錯誤:同理
}
#include
main() {
char str1[30], str2[20], *ptr1 = str1, *ptr2 = str2;
printf("input str1:"); gets(str1);
printf("input str2:"); gets(str2);
printf("str1------------str2\n%s.......%s\n", ptr1, ptr2);
while (*ptr2) *ptr1++ = *ptr2++; // 複製直到遇 \0
*ptr1 = '\0'; // 補上結束符
printf("str1------------str2\n%s.......%s\n", str1, str2);
}
機制:*ptr2 為當前字元值,非 0 進入迴圈;*ptr1++ = *ptr2++ 依優先序先取值指派,再遞增指標。
while (*ptr1) ptr1++; // 移動到 str1 結束符處
while (*ptr2) *ptr1++ = *ptr2++; // 附加 str2
*ptr1 = '\0'; // 新結束符
前提:str1 空間 ≥ strlen(str1)+strlen(str2)+1。
*ptr1++ 等價於 *(ptr1++) // 先取值,指標遞增
(*ptr1)++ // 取值後,所指內容遞增(需括號)
行 = i/列數, 列 = i%列數while(*src) *dest++ = *src++; + 補 \0*ptr++ 先取值後遞增指標,非遞增所指內容