C/C++ 二维数组
二维数组本来是一个很简单的知识点,但是因为C++的灵活度很高,导致不同的人,有不同的使用方法,并且在各自的语境下可能都能运行,但是换一个语境,可能就运行不了了。这里总结下二维数组的知识点,并且给出一个较为通用的一个使用方法。
二维数组构造方式:
首先给出二维数组的几种构造方式:
//自动分配,这种方式定义在栈内存上,不用手动销毁内存,缺点在于数组大小不能定义过大(栈内存)。
总结一下总共三种的使用方式:
- 自动分配,定义在栈内存上,类型是(int*)[5]
- 手动分配,定义在堆内存上,需要手动释放,类型是 int **, 每一维度可以变长
- 使用一维数组进行定义,需要手动进行寻址,类型int*
二维数组作为函数参数:
将二维数组作为函数参数的时候,本质上,只要保证实参和形参的数据类型一致那就没啥毛病,因此相应的有这么几种函数形参定义方式。
双指针形式:
void
这种函数传入形式,当然要求我们定义的实参也就是双指针形式,也就是第二种手动分配方式。
单指针形式:
void
这种形式的话,要求传入的实参是单指针
(int *)[5] 形式:
void
这种形式还有几种变种,比如 "int p[] [5]", 但是这种方式都会要求指定第二维度的长度,这是因为二维数组在内存的存储方式是行存储的,对于一个p[i] [j]的数组,实参仅仅传递了一个起始地址,要获取任意位置的地址,寻址方式为:p+i*cols+j。站在编译器的角度,你必须告诉它列长,才能够访问任意位置的地址。
![2e68c822a68d9262483c3fa882ea4d60.png](https://img-blog.csdnimg.cn/img_convert/2e68c822a68d9262483c3fa882ea4d60.png)
实参形参之间的相互转化:
本来吧,各自按照实参形参的定义,好好的传就可以了,但是呢,总有一些大神,会不按照常理出牌,定义了int[rows] [cols]格式的,但是却喜欢传入一个*p或者**p的形参函数。导致明明简单的问题变得复杂起来了。实际上我们可以把事情看得简单一点,函数的定义和函数的构造仍然只有三种,只不过多加了几种转换:
1. p[][5] -> int* p
*(p+i * cols+j)
2. int p[][5] -> int** p
*((int * )p+i * cols+j)”
3. int **p -> int *p
*((int*)p+i*cols+j)
4. int *p -> int **p
上述左边是实参类型,右边是形参类型。经过实验,1,2, 3是可行的,但是转换后不能使用p[i] [j]访问,需要手动的进行寻址,具体的寻址方式已经写上去了,4的转换是不可行的,是因为一维数组已经缺少了列信息,不可能恢复到二维数组。