无论 一/二维数组 传递参数本质 都是首地址的传送, 无法带下标传送,只能单独传送下标(下标本质就是地址偏移量),或约定下标长度! 一般数组 分配是在栈上进行的,能够保证所有元素的地址空间连续。 若使用malloc()在堆上分配空间,给数组则空间就不一定连续了
二维数组:
下面以在默认栈中定义数组访问形式分析:
把它分为三大类:
第一类 固定 行列 传参 : 行列 固定
第二类 固定 列 传参; 行参数动态:列 固定,行做为参数动态
第三类 行列动态 传参:列行做为参数动态
是否可以 行列 都是动态,还不用传递行列形参,是否能做到呢? 答案:做不到。因为数组传递本质是指针参数传递,也就是地址传递。指针就是地址。传递过来的地址,是无法知道数组长度的。
第一类 固定 行列 传参
声明 / 定义形式
void Fun(int buf[2][3] ) //第一种 形参为数组
void Fun(int buf[ ][3] ) //第一种 形参为数组,可省略第一维,第二维就不可省略(由编译器的寻址方式决定第二维就不可省略)
void Fun(int (*buf)[3] ) //第二种 形参为数组指针,注意:不是(int *a[n])(指针数组) ,而是(int (*a)[n])(数组指针),因为 优先级: () 大于 [] 大于 *
形参操作形式
buf[i][j] //访问的是 第 i 行 第 j 列
*(buf[i] + j) //同上
*(*(buf+i) + j) //同上
*((int *)buf + i*n +j) //同上,n表示第二维数组长度,即列宽
调用形式
Fun(ary); //void Fun(int buf[2][3] ); void Fun(int buf[ ][3] ); void Fun(int (*buf)[3] ) 的调用形式
示例代码:
#include <stdio.h>
//void Fun(int buf[2][3] ) //第一种 形参为数组
//void Fun(int buf[ ][3] ) //第一种 形参为数组,可省略第一维,第二维就不可省略(由编译器的寻址方式决定第二维就不可省略)
void Fun(int (*buf)[3] ) //第二种 形参为数组指针,注意:不是(int *a[n])(指针数组) ,而是(int (*a)[n])(数组指针),因为 优先级: () 大于 [] 大于 *
{
int i, j;
for(i=0; i<2; i++)
{
printf("buf[%d][0] = ", i);
for(j=0; j<3; j++)
{//四种操作形式
printf("%d ", buf[i][j]);
printf("%d ", *(buf[i] + j));
printf("%d ", *(*(buf+i) + j));
printf("%d ", *((int *)buf + i*3 +j));
}
printf("\r\n");
}
}
void main()
{
int ary[][3] = { {1, 2, 3}, {4, 5, 6} };
int i, j;
printf("\r\n数组传参数前:\r\n");
for(i=0; i<2; i++)
{
printf("ary[%d][0] = ", i);
for(j=0; j<3; j++)
{
printf("%2d ", ary[i][j]);
}
printf("\r\n");
}
printf("\r\n数组传参数后:\r\n");
Fun(ary);
}
运行结果:
第二类 固定 列 传参; 行参数动态
声明 / 定义形式
void Fun(int buf[2][3], int m) //第一种 形参为数组
void Fun(int buf[ ][3], int m) //第一种 形参为数组,可省略第一维,第二维就不可省略(由编译器的寻址方式决定第二维就不可省略)
void Fun(int (*buf)[3], int m) //第二种 形参为数组指针,注意:不是(int *a[n])(指针数组) ,而是(int (*a)[n])(数组指针),因为 优先级: () 大于 [] 大于 *
调用,操作都是同第一类一样,只是行可变;
第一类 和 第二类 都是一个共同特点 第二维 不能省略, 也就意味着 第二维 (列) 不能动态 作为形参
第三类 行列动态 传参
**若 行列动态 / 列动态 怎么办?**有办法
声明 / 定义形式
void Fun(int **buf, int m) //第三种 形参为二级指针,m表示第一维数组长度,即行宽,列固定
void Fun(int **buf, int n) //第三种 形参为二级指针,n表示第二维数组长度,即列宽,行固定
void Fun(int **buf, int m, int n) //第三种 形参为二级指针,行列动态
形参操作形式
*((int *)buf + i*n +j) //同上,n表示第二维数组长度,即列宽, 只能这种操作
调用形式
Fun((int **)ary, m); //只能这样调用
Fun((int **)ary, n); //只能这样调用
Fun((int **)ary, m, n); //只能这样调用
代码示例:
#include <stdio.h>
void Fun(int **buf, int m, int n) //第三种 形参为二级指针
{
int i, j;
for(i=0; i<m; i++)
{
printf("buf[%d][0] = ", i);
for(j=0; j<n; j++)
{
printf("%d ", *((int *)buf + i*3 +j));
}
printf("\r\n");
}
}
void main()
{
int ary[][3] = { {1, 2, 3}, {4, 5, 6} };
int i, j;
printf("\r\n数组传参数前:\r\n");
for(i=0; i<2; i++)
{
printf("ary[%d][0] = ", i);
for(j=0; j<3; j++)
{
printf("%2d ", ary[i][j]);
}
printf("\r\n");
}
printf("\r\n数组传参数后:\r\n");
Fun((int **)ary, 2, 3);
}
运行结果: