C/C++中多维数组做参数情况的详细解释

我大二刚学完C语言,之后用来写矩阵分析的时候想把二维矩阵直接传到函数里,结果出现了问题:形参实参类型不一致,无法通过编译!随后我就尝试各种方法(改变形参或者实参的格式),虽然最后通过了不过当时还是没理解原理。

后来自己把原因分析出来了,现在把它写出来,希望对碰到同样问题的朋友有所帮助。

转载请注明出处,谢谢!

几个跟参数有关的知识:C/C++的函数形参可以是普通类型、指针、引用。传值方式有两种:值传递(包括指针)、引用。  传参时从左往右,结合时从右往左,这个很重要(函数默认值与此有关)。 

参数是指针时,我们一般通过两种方式实现读写:①移动指针 p++  ② p+i(目标位置)或者 p[i],等同于寻址的方式实现,他们实现时在内存里的操作: 一维 p+0(p[0]) p+1(p[1]) p+2(p[2]) ······ p+(n-1)  (p[n-1]) 由于作图不太方便,下面的讲解就不附图了。

1、一维数组(指针)  

做参数 一般指针做参数我就不多说了,专门搜这种问题的人应该都懂。

下面说一下一维数组: 一般传参情况:字符串、整型数组(举个特例,实际上字符串是字符型数组)。 字符串,我们一般用下面这种方式: 


bool PrintStr(char* str)//char str[]也一样
{
	if (NULL == str || "" == str)
	{
		return false;
	}
	for (int i = 0; i < strlen(str);i++)//就不考虑效率了,注意不要用sizeof
	{
		cout << str[i] << "  ";
	}
	while ('\0' != *str)//通过指针
	{
		cout << *str++ << "  ";
	}
	return true;
}



2、二维数组做参数



在一维中我们看到,遍历数组时必须有终止条件,可以是某种标志也可以规定移动次数。
当到二维的时候这种情况就更为复杂。很多人定义函数的时候将函数定义为双重指针,传参的时候直接把二维数组名放进去,例如:


//matrix 一维矩阵,m 矩阵行数,n矩阵列数
bool PrintMatrix(int** matrix,int m,int n)
{
	return true;
}


int main(void)
{
	int arr[3][3] = {1,2,3,4,5,6,7,8,9};
	
	PrintMatrix(arr,3,3);
	return 0;
}

这时候会提示错误:无法从int[3][3]转为int**,类型不兼容!

当然会不兼容!
函数传参的时候并不是你想的那样,他需要知道传入参数的特征:二维数组,数组每一维占多大。因为在函数里面读写实际是以*(p+i) 或者 p++的形式操作的。
二维数组如果那样操作会怎么样?我从第一行跳到第二行,你会这么写  p+1 或者 p++,可是函数怎么操作?
int**p,p+1每次移动sizeof(int*) ==4个字节,*p+1每次会移动sizeof(int)个字节;int p[3][3],p+1每次移动sizeof(p[0]) ==3*4个字节,*p+1每次会移动sizeof(int)个字节。它们是不能等同看待的,否则很容易出现内存错误,甚至系统崩溃。

所以在定义函数的时候如果是一维就可以省略,因为指针是按照sizeof(指针类型)移动;而在二维的时候则必须告诉函数一维以后的数据布局,这样它才不会读写错误甚至越界,一维部分也可以省略。

从抽象而且直接的角度,你也可以这么理解:一维的在内存中线性排列,读写的时候也是线性操作,所以通过了。当你需要处理的内容是非线性的时候,不仅仅要告诉函数我的内容是非线性的,还要告诉他非线性的特征:二维数组,数组每一维特征(空间大小)

例如:

#define M 3
#define N 3
//matrix 一维矩阵,m 矩阵行数,n矩阵列数;
//M、N必须是常数,而且N必须和传入的参数一致
bool PrintMatrix(int matrix[M][N], int m, int n)
{
	return true;
}
//matrix 一维矩阵,m 矩阵行数,n矩阵列数
//M甚至可以省略,因为有类型int
bool PrintMatrix(int matrix[][N], int m, int n)
{
	return true;
}


//matrix 一维矩阵,m 矩阵行数,n矩阵列数
//当然可以这么写,它本来就是这个样子!
bool PrintMatrix(int (*matrix)[N], int m, int n)
{
	return true;
}

按照上面的方式完美通过,Perfect!


3、多维数组做参数



多维数组和二维数组类似,只不过需要多加几个说明:

例如:int p[M][N][K] ,p[0][0][0+1] 指针移动移动一个类型长度4byte==sizeof(int),p[0][0+1][0] 指针移动一个维 K*sizeof(int),p[0+1][0][0]指针移动二维N*(K*sizeof(int))。

#define M 3
#define N 3
#define K 3
bool PrintMatrix(int(*matrix)[N][K], int m, int n,int k)
{
	return true;
}


4、总结



通过上面分析可以看出多维指针比较复杂,很容易出错。所以实际用的时候一般用其它方法绕过这个问题:数据整理为一维,处理完后再转成原形式;用结构体或类;一维一维的处理等。

PS:今天登陆发现编码出问题,重新编辑了一下



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值