咋一看,顺手就写出下面的代码
下面就一个矩阵的加法演示可能出现的问题
void addMatrix(int row, int col, int **a, int **b, int **c) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
c[i][j] = a[i][j] + b[i][j];
}
}
}
int main(int argc, char *argv[])
{
int a[5][1] = {1};
int b[5][1] = {0};
int c[5][1] = {0};
addMatrix(5, 1, a, b, c);
return 0;
}
很尬杠,编译出错了。错误信息
error: cannot convert ‘int (*)[1]’ to ‘int**’
类型不匹配,为什么出现类型不匹配呢?
那么,int (*)[1]
表示什么呢?
表示只有1列的数组,也就是数组指针,修饰指针的。所以其实是一个指向数组的指针,也就是数组的行指针
2 修改
机智的你会修改下参数,比如将输入参数强转int **
addMatrix(5, 1, (int **)a, (int **)b, (int **)c);
很遗憾,运行错误,这又是为什么呢?
我觉得是,把二维数组强制转换成int**,让其丢失了数组的列信息,导致使用下标的时候出错
具体而言,就是下标寻址,编译器不知道一行有多少,也就col未知,因为你已经强转成int **,丢失了数组一行的个数
3 把二维数组当成一维数组用
这里的函数形参全是一维指针,也就是入参的一行,即a[0]
void addMatrix(int row, int col, int *a, int *b, int *c) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
c[i*col+j] = a[i*col+j] + b[i*col+j];
}
}
}
int main(int argc, char *argv[])
{
int a[5][1] = {1};
int b[5][1] = {0};
int c[5][1] = {0};
addMatrix(5, 1, a[0], b[0], c[0]);
//addMatrix(5, 1, (int *)a, (int *)b, (int *)c);
return 0;
}
这样,就需要手动计算下下标值i*col+j
,其实,本质上讲,这样写效率没区别。因为下标的方式也是转成i*col+j
,只是下标的方式容易理解,如果真要较真的话,可以说下标的方式会慢些。
4 其他方式
下面的方式也是可以的,表示输入的1列的二维数组,但是没什么实用价值,因为提前不知道有多少列,写成1就只适用1列的二维数组。
当然你也可以使用C++的模板推测。
void addMatrix(int row, int col, int (*a)[1], int (*b)[1], int (*c)[1]) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
c[i][j] = a[i][j] + b[i][j];
}
}
}
5 需要传入二维数组吗?
起初,我感到很纳闷,为什么要传入二维数组?因为二维数组我都是在函数内部new出来的,直接用二维指针接收的,换句话说,二维指针其实用于接收函数内部计算的结果。
这样有什么好处呢?
- 栈大小有限制,无法定义很大的二维数组
- 如果把二维数组当成入参,其实默认是带了一个列的信息,否则无法适用下标,换句话说二维指针不带列信息,无法进行下标运算!!!