You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言二维数组传参:int**与int[][N]的区别及崩溃原因问询

为什么用int**接收二维数组会崩溃,而int [][N]可以?

这问题我刚学C的时候也踩过一模一样的坑!核心是**int**和C语言里的二维数组在内存结构上完全是两回事**,千万别把它们划等号。

先搞清楚二维数组的真实模样

你定义的int arr[][3] = { {1,2,3}, {4,5,6}, {7,8,9} },在内存里是一整块连续的空间,排列顺序就是:1, 2, 3, 4, 5, 6, 7, 8, 9,没有任何额外的指针存储。

当你把这个二维数组传给函数时,它会自动“退化”成一个指向行的指针——也就是int (*)[3]类型,意思是“指向一个包含3个int的数组的指针”。这个指针直接指向数组的第一行起始地址,访问arr[i][j]的时候,编译器会帮你计算正确的内存偏移:首地址 + i*3*sizeof(int) + j*sizeof(int),完全不用额外的指针跳转。

再看int**到底是什么

int**是指向指针的指针,它对应的是「指针数组」的结构。比如你这么定义:

int row1[] = {1,2,3};
int row2[] = {4,5,6};
int row3[] = {7,8,9};
int* ptr_arr[] = {row1, row2, row3};

这个ptr_arr就是一个指针数组,内存里先存三个指针地址(分别指向row1、row2、row3的起始地址),然后这三个指针再各自指向不同的int数组块。这时候ptr_arr退化后就是int**类型,用int**接收完全没问题,访问ptr_arr[i][j]时,会先解引用ptr_arr[i]拿到对应的行指针,再偏移j个int,逻辑完全正确。

为什么传二维数组给int**会崩溃?

当你把二维数组arr(类型是int (*)[3])传给print函数的int** arr参数时,编译器虽然可能会给你警告,但还是会强行做类型转换。但到了函数里执行arr[i][j]的时候,问题就来了:

编译器会按照int**的逻辑去计算地址:先取arr的值(也就是二维数组的首地址,对应数值1的地址),把它当成一个指针的地址,解引用后得到的是1(因为首地址存的是第一个元素的值1),然后再把1当成一个指针去访问偏移j的位置——这显然是非法内存访问,直接触发程序崩溃。

为什么int [][N]就正常?

当你把print函数的参数改成int arr[][N]时,它的本质其实还是int (*)[N]——和二维数组退化后的指针类型完全匹配。这时候函数里的arr[i][j]会按照二维数组的内存布局计算偏移,自然就能正确访问到每个元素,程序也就正常运行了。

一句话总结

  • 二维数组是连续内存块,退化为指向行的指针int (*)[N]
  • int**对应离散的指针数组,是指向指针的指针
  • 两者类型不匹配,强行混用会导致内存访问错误,引发崩溃

内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:18:25