当前位置: 首页 > 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.jsqmd.com/news/103953/

相关文章:

  • 告别熬夜!百考通AI一键生成毕业答辩PPT,让你告别“做PPT恐惧症”
  • 推荐一个开源神库!用一句话就能“变出”一套专业级PPT文稿!
  • 2025年12月聚乳酸面料源头厂家权威推荐榜:聚乳酸纤维/石墨烯聚乳酸/聚乳酸内衣/聚乳酸抹布,绿色科技与舒适体验创新之选 - 品牌企业推荐师(官方)
  • 神经紧张素受体SORT1
  • 某211高校讲师晒工资条,网友:公积金数额令人瞩目...
  • 【云计算】【Kubernetes】 ⑥ K8S Pod优雅下线全解析:从preStop到Eureka下线实战
  • 有哪些小众的开源项目养活了一大批人?
  • 穗佛双城联动!2026精密紧固件产业双线商机盛典
  • 百考通AI:你的智能数据分析专家,从数据到洞察,一键生成专业报告
  • Nature Electronics 一种用于多模态皮肤信号监测的柔性触觉接口
  • 血浆多组学网络如何揭示急性早幼粒细胞白血病的病理机制?
  • MyBatis-Flex 来了!完爆MyBatis-Plus?
  • 小鼠T细胞激活:如何系统解析其发育分化与免疫功能表征?
  • 小鼠T细胞激活试剂盒:如何通过CD3/CD28双信号系统实现高效免疫激活?
  • EmotiVoice本地化部署优势:数据安全与响应效率兼得
  • 2025年十大超声波浓度计制造厂排行榜,推荐超声波浓度计厂 - mypinpai
  • 硫辛酸酯标记聚乙二醇单甲醚:mPEG-LA 的核心应用场景
  • 小鼠分型试剂盒:如何通过高维流式技术实现免疫系统的全景解析?
  • 某大厂员工:选leader-定要选有家庭财富相对自由的中年人,如果你的leader是个奋斗b、光棍,那你注定就是他的垫脚石~
  • 美亚 4.4 星评,从 10 个真实案例出发,OpenAI 一线工程师讲透大模型系统设计实战!
  • 低代码物联网平台
  • 【Java毕设全套源码+文档】基于springboot的数据库课程在线教学系统设计与实现(丰富项目+远程调试+讲解+定制)
  • 深度测评汉唐数字传媒新媒体运营有实力吗、短视频运营能力及专业 - myqiye
  • 泳池漆源头厂家推荐,看看哪家性价比高? - mypinpai
  • 解决孩子叛逆的学校哪家强?矫正孩子叛逆的学校选哪家? - 工业推荐榜
  • 中央空调品牌怎么选?靠谱又高性价比之选来了 - myqiye
  • 2025年年终贵阳管道疏通推荐:专业排行解析与多维度服务对比指南 - 品牌推荐
  • 2025年自动化变频控制柜厂家哪家强?这份榜单告诉你,物联网远程控制柜/PLC控制柜/水泵专用控制柜自动化变频控制柜公司排行榜 - 品牌推荐师
  • 探寻吉田美学化妆培训:靠谱、高性价比之选 - 工业推荐榜
  • 2025年视频制作行业领军者:谁在服务全球知名品牌?视频制作公司推荐排行聚焦优质品牌综合实力排行 - 品牌推荐师