C语言2D数组指针函数传参原理及代码疑问求助
二维数组传入函数的访问逻辑解析
原代码第7行的工作原理
你的代码里,print函数的参数arr被声明为int *类型——这相当于把二维数组当成连续的一维内存块来处理。C语言中,二维数组在内存里是按行连续存储的,比如你的arr在内存中的布局是:1,2,3,4,5,6,7,8,9,没有间隙。
第7行的*((arr+i*n) + j)可以拆成两步理解:
arr+i*n:计算第i行的起始地址。因为每行有n个int元素,所以跳过前i行的i*n个int,得到第i行第一个元素的指针。+j:在第i行的基础上,再往后移动j个int,指向第i行第j列的元素。- 外层的
*解引用这个指针,拿到对应位置的数值。
这种写法本质是手动模拟了二维数组的内存寻址,把二维结构转换成一维指针来操作。
*( *(p + i) + j)失效的原因
*( *(p + i) + j)是**针对二维数组指针(指向一维数组的指针)**的标准访问写法,但你的print函数参数是int *,不是这种类型,所以会出错:
- 当
p是int *类型时,p+i的含义是:指针向后移动i个int的位置(偏移量为i*sizeof(int)),而不是移动i行。 - 此时
*(p+i)得到的是一个int值(不是指向一维数组的指针),你再对这个int值做+j的指针运算,属于非法操作——C语言不允许把普通整数当成指针来使用,编译器会报错或者运行时崩溃。
如果想使用*( *(p + i) + j)的写法,需要把函数参数改成指向一维数组的指针,示例如下:
#include <stdio.h> // 参数是指向包含3个int的数组的指针 void print(int (*arr)[3], int m) { int i, j; for (i = 0; i < m; i++) for (j = 0; j < 3; j++) printf("%d ", *(*(arr + i) + j)); } int main() { int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int m = 3; print(arr, m); // 无需强制类型转换 return 0; }
这里arr作为参数传入时,会自动转换成int (*)[3]类型(指向3个int的数组的指针),arr+i会移动i*sizeof(int[3])的字节数(即跳过一整行),*(arr+i)得到第i行的数组名(再转成指向该行第一个元素的指针),最后+j就能定位到目标元素。
内容的提问来源于stack exchange,提问作者Draisen
相关产品推荐
相关产品推荐

