最近在百度知道看到很多提问是关于RT的一些提问,下面是我在学习的过程中的一些总结,当然大虾可以忽视的,只是给初学者一些参考。
一 二维数组动态申请空间
假设我们要申请一个m行n列的整形数组,m、n的值可以在程序中动态改变
1 使用malloc和free:
int **buf;
//申请
buf =(int **)malloc(sizeof(int *)*m);
for(int i=0;i<m;i++)
buf[i]=(int *)malloc(sizeof(int)*n);
//释放
for(int i=0;i<m;i++)
free(buf[i]);
free(buf);
2 使用new和delete:
int **buf;
//申请
buf=new int*[m];
for(int i=0;i<m;i++)
buf[i]=new int[n];
//释放
for(int i=0;i<m;i++)
delete [](buf[i]);
delete []buf;
二 二维数组函数传参
主要有以下三种方法,且以三种方法都是把数组地址作为参数传入
1 void foo(int a[][4]); //4可以为任一整型常数或者整形常量,不能为变量
函数foo必须传入一个列数为4的整形二维数组作为实际参数,行数可以任意,如:
int a[5][4];
foo(a);
但是不能传入一个二维指针,即使该指针已经申请了空间的列数为4,如以下做法是错误的
int **a;
申请5行4列的空间
foo(a);
2 void foo(int a[3][4]); //3、4可以为任一整型常数或者整形常量,不能为变量
此方法等价与方法1,形参中第一维大小实际上不起任何作用
3 void foo(int **a);或者增加两个参数:实际数组的行数m和列数n void foo(int **a,int m,int n);
函数foo必须传入int** 类型的实际参数,且传参之前要动态申请空间,如:
int **a; (例1)
申请5行4列的空间
foo(a);
但是不能传入一个静态定义的二维数组的地址,以下做法是错误的
int a[5][4];
foo(a);
把a进行强制类型转化不行吗,比如foo( (int **)a ), 我的回答是可以,但是需要注意一个非常重要的问题:
假设foo定义为 void foo(int **a){ int i=1,j=1; a[i][j]=2 }
实际调用如下:
int a[5][4]; (例2)
foo( (int **)a );
此时编译可以通过,但是程序运行会出现错误,因为此时编译器计算a[i][j]时寻址发生错误
对一个m行n列的二维数组a,计算a[i][j]时,编译器如下寻址*((int*)a + n*i + j); 例2中a[5][4]强制转化为int ** 后,编译器不知道数组的列数n,因此无法寻址。但为什么例1中动态申请空间时却可以正确寻址,这是因为申请空间时,编译器就记下了二维地址a的行数和列数。
所以要想像例2那样调用,foo函数中就不能出项类似于a[i][j]的表达式,我们要自己手动寻址,并且至少要有数组的列数作为参数,如下
foo定义为 void foo(int **a,int m,int n){ int i=1,j=1; *((int*)a + n*i + j)=2 }
int a[5][4];
foo( (int **)a );
这样就没有错误了