当前位置: 首页 > news >正文

把一维数组硬当成二维用:一次讲透 C 语言“指向数组的指针”

1. 故事开场:一段“诡异”代码

int a[] = { 10,12,30,14,50,60,71,800,900,1000,1100,1200 };
int (*p)[4] = (int (*)[4])a;
printf("%d\n", p[1][2]);   // 输出 71

短短三行,把不少同学看懵:
“一维数组怎么突然 p[1][2] 了?”、“int (*p)[4] 到底是个啥?”

下面按“理解→实战→总结”三步,一次性拆干净。


2. 拆开类型: int (*p)[4] 怎么读

写法 含义 加减 1 的步长
int *p 指向 单个 int sizeof(int)
int (*p)[4] 指向 一整行 4 个 int 的数组 4*sizeof(int)

记忆技巧:
(*p) 看成整体,它就是“数组名”,p 自然就是“指向那个数组的指针”。
括号必不可少,否则 int *p[4] 变成“指针数组”——语义完全不同。


3. 内存布局:为什么 p[1][2] 是 7

强转之后,编译器把原内存按“每 4 个 int 一行”重新解释:

地址低 → 高
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|   1    |   2    |   3    |   4    |   5    |   6    |   7    |   8    |   9    |   10   |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+\____________  row 0  __________/ \____________  row 1  __________/ \_____  row 2 _____/
  • p 指向 row 0
  • p + 1 跳过 一整行 → 指向 row 1 的首元素 5
  • *(p + 1) 拿到 row 1 这一整行(数组)
  • [2] 取下标 → 拿到 7

4. 实战场景:什么时候真有必要用“指向数组的指针”

场景 int (*p)[N] 的理由 用普通 int *p 的痛点
二维数组传参 列宽 N 写进类型,编译期检查;函数内仍可用 p[i][j] 语法 列宽靠额外参数,易传错;索引需手动 i*col+j
按行迭代 p++ 一次跳一行,代码短 只能 q += col,列宽一改全得改

示例:类型安全的传参

void foo(int (*row)[4], int n_row)
{for (int i = 0; i < n_row; ++i)printf("%d\n", row[i][2]);   // 直接写列号 2
}int main(void)
{int m[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};foo(m, 3);          // 列宽 4 已硬编码在类型里
}

若误传 int x[3][5],编译器立刻报错,防止越界。


5. 易混雷区: m[1] 到底是不是指针?

int m[3][4] = {...};
printf("%p\n", (void*)m[1]);   // 能打印地址
printf("%d\n", *m[1]);         // 输出 5
printf("%d\n", m[1][1]);       // 输出 6
  • m[1] 类型int[4]——数组,不是指针。
  • 只有当数组出现在 下标运算、函数实参 等上下文时,编译器才临时把它退化成 int*
  • 因此 *m[1] 等价于 *(m[1]退化后的指针 + 0),拿到首元素 5
    m[1][1] 等价于 *(m[1]退化后的指针 + 1),拿到 6
  • *m[1][1] 会报错,因为 m[1][1] 已是纯 int,不能再解引用。

6. 小结一张图

源码写法          实际类型           步长(+1)        常见用途
int *p            int *              sizeof(int)       一维/扁平缓冲区
int (*p)[4]       指向int[4]         4*sizeof(int)     二维数组按行传参、按行迭代
int *p[4]         4个int*的数组      sizeof(int*)      指针数组(完全不同)

7. 结语

  • 日常元素访问直接写 m[i][j] 最清爽。
  • 一旦涉及“把二维数组当整体传参”或“按行遍历”,int (*p)[N]唯一能把列宽写进类型、让编译器帮你查错 的利器。
  • 记住“数组名先退化再运算”这条核心规则,一切指针花样都会变得透明。

希望这篇小文能把“指向数组的指针”彻底从玄学变成工具,不过是让编译器记住‘一行有多宽’罢了!”

关键词:C 语言、数组退化、指向数组的指针、二维数组传参、指针运算

http://www.gsyq.cn/news/114759.html

相关文章:

  • 神经紧张素受体SORT1
  • 【云计算】【Kubernetes】 ⑥ K8S Pod优雅下线全解析:从preStop到Eureka下线实战
  • 百考通AI:你的智能数据分析专家,从数据到洞察,一键生成专业报告
  • 血浆多组学网络如何揭示急性早幼粒细胞白血病的病理机制?
  • EmotiVoice本地化部署优势:数据安全与响应效率兼得
  • 小鼠分型试剂盒:如何通过高维流式技术实现免疫系统的全景解析?
  • 硫辛酸酯标记聚乙二醇单甲醚:mPEG-LA 的核心应用场景
  • 【Java毕设全套源码+文档】基于springboot的数据库课程在线教学系统设计与实现(丰富项目+远程调试+讲解+定制)
  • 深度测评汉唐数字传媒新媒体运营有实力吗、短视频运营能力及专业 - myqiye
  • 2025年年终贵阳管道疏通推荐:专业排行解析与多维度服务对比指南 - 品牌推荐
  • 探寻吉田美学化妆培训:靠谱、高性价比之选 - 工业推荐榜
  • 电子取证实验室建设指南:加密破解工具的技术路径与选型考量
  • 《60天AI学习计划启动 | Day 30: 前端 + AI 组件化封装 能力盘点》
  • 2025年口碑好的侧推装箱机厂家推荐及选购参考榜 - 行业平台推荐
  • 【量子计算镜像运行参数全解析】:掌握5大核心参数优化性能
  • 基于 Spring·Boot和 Vue 框架的校园快递代领系统设计与实现
  • 2025年12月兰州靠谱寒假伴学班精选 - 2025年品牌推荐榜
  • 【高并发AI系统构建秘诀】:如何用Docker优化LangGraph Agent负载能力
  • 2025年热门的自动化装箱机用户口碑最好的厂家榜 - 行业平台推荐
  • 揭秘Docker Scout漏洞导出功能:如何快速获取镜像安全报告
  • 【从理论到落地】:构建安全Agent服务的Docker隔离体系(附完整配置清单)
  • 为什么90%的AI项目失败在部署?Docker解决方案全公开
  • Docker Offload状态同步机制全剖析,资深架构师绝不外传的底层逻辑
  • 2025年兰州GEO公司Top5推荐 - 2025年品牌推荐榜
  • 从本地开发到云端上线:Docker与Vercel AI SDK无缝对接全解析
  • 《60天AI学习计划启动 | Day 25: AI 对话前端体验与产品设计(和你现在的 AIChat 强相关》
  • 【Agent服务灾备终极指南】:Docker环境下备份恢复的5大核心策略
  • 2025年熔覆耐磨板,耐磨复合钢板,双金属耐磨板厂家推荐,冶金行业高温工况防护之选 - 品牌鉴赏师
  • 无人机培训基地哪家比较专业?国内优质机构解析 - 品牌排行榜
  • 3分钟搞定边缘 Agent 部署:高效 Docker 启动脚本编写秘籍