## 数组指针 vs 指针数组 ## 判别规则(核心,唯一要记的) - 看变量名**先跟谁结合**:无括号 `int *p[10]` → `[]`(优先级高于 `*`)先结合 → p 是**数组**(指针数组) - 有括号 `int (*p)[10]` → `*` 先结合 → p 是**指针**(数组指针) 一句话:**"`[]` 优先级高,没括号 p 是数组;括号护住 `*`,p 才是指针。"** ## 抽象描述(一句话本质) C 声明结合优先级:`[]`(下标)比 `*`(解引用)高。判断身份 = 看变量名先跟谁结合——跟 `[]` 先结合是数组,被括号包住先跟 `*` 结合是指针。数组指针配 `&a` 或二维数组传参;指针数组就是"数组里装指针"。 ## 正反例(建立直觉) - **正例1**:`int *p[10]` —— 指针数组。p 先和 `[10]` 结合 → p 是数组,每个元素是 `int *`。用法:`p[0]` 是一个指针,指向别处的 int - **正例2**:`int (*p)[10]` —— 数组指针。`(p)` 括号先和 `*` 结合 → p 是指针,指向 `int[10]` 整块。用法:`int a[10]; int (*p)[10] = &a; (*p)[i]` 取元素 - **正例3**:二维数组传参 `int m[3][4];` → 形参 `int (*p)[4]`(指向一行的指针),退化成"指向第一行的指针" - **反例1**:背反——以为 `int *p[10]` 是"指向数组的指针" → 错,`[]` 优先级高,p 先是数组 - **反例2**:以为 `int (*p)[10]` 能指向任意 int → 错,只能指向 `int[10]`,`int x; int (*p)[10] = &x;` 类型不匹配报错 ## 易混对比 | | `int *p[10]` | `int (*p)[10]` | | -------- | --------------------------- | ---------------------------- | | p 是什么 | **数组**(10 个指针) | **指针**(指向 int[10]) | | 名字 | 指针数组 | 数组指针 | | 为什么 | 无括号,`[]` 优先级高先结合 | `(p)` 括号先和 `*` 结合 | | 怎么用 | `p[0]` 是指针,指向单个 int | `(*p)[i]` 取元素,指向一整块 | ## 变体验证(3 题,全过=学会) 1. `int a[2][3];` 传参 → 退化成指向第一行的指针,形参写 **`int (*p)[3]`** 2. 陷阱题:32 位平台上 `int *p[3];` 的 `sizeof(p)` = **12**(3 个指针);`int (*q)[3];` 的 `sizeof(q)` = **4**(1 个指针)——身份不同,sizeof 立刻露馅 3. `int arr[5]; int (*pa)[5] = &arr;` → `(*pa)[2]`、`pa[0][2]`、`arr[2]` **三者完全相等,不报错**(`pa[0]` 解引用出 arr 本身);真正越界的是 `pa[1][2]`——`pa+1` 跨过整整一块 int[5] ## 口述要点(面试怎么讲) - **结论先行**:看变量名先跟谁结合——无括号 `[]` 优先 = 数组;括号护 `*` = 指针 - **为什么一个括号改变一切**:`[]` 优先级高于 `*`,括号强制改变结合顺序,类型就完全不同 - **二维数组传参为什么列数不能省**:列数决定"一行多大",指针运算步长需要它, 这样才能运算p[i][j](`p+1` 要跨一整行);行数能省,因为退化成指针后只指向第一行,单个指针的步长跟有几行无关 - **步长思想**:`p+1` 跨一整行 / `&a+1` 跨一整块——"指向什么类型,+1 就跨多大" - **易错点**:`p[1][2]`(p 是 `int(*)[4]`)= 指向二维数组的第 1 行第 2 列(即 `m[1][2]`),不是报错 ## 关系网络 | 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 | | -------------- | ------------------------------------------------------------------- | ---------------------------- | | 数组名 vs 指针 | `&a` 的类型就是 `int(*)[N]`——数组指针正好接 `&a`;`a` 退化成 `int*` | 把`&a` 和 `a` 混用,步长全错 | | 二维数组传参 | `int m[3][4]` 传参退化 → `int (*)[4]`(行指针),行数可省列数不可省 | 以为传二维数组要传`int **` | | 声明优先级 | `[]` > `*`,括号改结合 | 靠背名字而不是看结合 | | 函数指针 | `int (*fp)(int)` 同款括号思想——括号护住 `*` 让 fp 先是指针 | 以为括号可有可无 | ## 学习日期 2026-08-03 --- _每主题一页,复习时只翻本目录。_