這是 C 語言指針進階的必考知識點,也是面試高頻題。核心區別在於「誰是主體」:
int *p[3] → 含 3 個 int* 的數組。int (*p)[3] → 指向含 3 個 int 的數組的指針。[] 優先級高於 *| 聲明 | 結合順序 | 含義 |
|---|---|---|
int *p[3] | p[3] 先結合 → *p[i] | 指針數組:3 個 int 指針 |
int (*p)[3] | (*p) 先結合 → 指向數組 | 數組指針:指向 int[3] 的指針 |
#include <stdio.h>
void main() {
// ---------- 數組指針:遍歷二維數組 ----------
int s[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int (*p)[4] = s; // p 指向 int[4] 類型,s 退化為首行地址
printf("數組指針遍歷二維數組:\n");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
// *(*(p+i)+j) 等價於 p[i][j]
printf("%d\t", *(*(p + i) + j));
}
printf("\n");
}
// ---------- 指針數組:存儲字符串/多行文本 ----------
char *t[] = { "Hello", "nihao", "C" }; // t 是 char*[3]
printf("\n指針數組存儲字符串:\n");
for (int i = 0; i < 3; i++) {
puts(t[i]); // 等價於 printf("%s\n", t[i]);
}
getchar();
}
數組指針遍歷二維數組: 1 2 3 4 5 6 7 8 9 10 11 12 指針數組存儲字符串: Hello nihao C
| 場景 | 指針數組 int *p[N] | 數組指針 int (*p)[M] |
|---|---|---|
| 存儲多個不定長字符串 | ✅ char *argv[] | ❌ |
| 遍歷/操作二維數組 | ❌ (需退化為指針數組) | ✅ 保持行結構信息 |
| 函數參數傳遞二維數組 | void f(int *p[], int n) | void f(int (*p)[M], int n) |
| 動態分配二維數組 | 逐行 malloc (不連續) | 一次性 malloc (連續內存) |
| main 參數 | char *argv[] / char **argv | 不適用 |
// 指針數組方式:不連續內存,靈活但碎片化 int **arr1 = malloc(3 * sizeof(int*)); for (int i=0; i<3; i++) arr1[i] = malloc(4 * sizeof(int)); // 數組指針方式:連續內存,緩存友好 int (*arr2)[4] = malloc(3 * sizeof(int[4])); // 或 malloc(3*4*sizeof(int)) // 訪問 arr2[i][j] 同靜態數組,釋放只需 free(arr2)
指針數組適合管理多個獨立對象(字符串、行數組、異構數據);數組指針適合操作規則的多維數組,保持內存連續性與類型安全。看懂聲明的關鍵:找核心標識符,按優先級結合,向外層層展開。掌握此區別,可避免 80% 的指針相關 Bug。