有时候我们不确定要输入多少个数据的时候,盲目的创建一个十分长的数组很占我们桟区的内存,甚至有可能长度不够导致指针的越界访问;或者我们创建数组而后面用不到时,不及时的销毁也是会占用内存。因此我们需要用动态数组进行数组的动态内存创建。动态数组是非常重要的,可反映一个程序员对内存的合理利用的好习惯,这个习惯对后面写项目(包含了几千上万行代码)有重要的影响,如果创建的无数变量不及时释放将会引起stack -overflow—栈溢出。那么我们就来看看动态数组:

所用函数库及函数:函数库是stdlib.h 函数常用的有两个,一个是

void* malloc(size_t size) 这个函数的传入值是所要创建数组的内存大小(长度*单元素内存大小)返回值是指向数组第一个元素的无类型指针,不会对数组进行初始化。所以我们要注意强制类型转换一下。

void* calloc(size_t nitems,size_t size)这个函数的传入值有两个,分别是数组的长度,以及每一元素的大小,一般地,我们可以用sizeof(类型)来做输入值,防止long这种大小不太确定的出错。返回值也是指向第一个元素的无类型指针,会对所以元素初始化为0,。也要注意强制类型转换一下。

另外:我们还有个放大和缩小数组长度的函数:void *realloc(void *ptr, size_t size),ptr是我们要改变内存(长度*单位内存)的内存块(数组第一个元素的地址),如果为空指针则会创建新的内存;size是我们要改变后的内存块内存,如果size==0&&ptr!=NULL则会释放对应内存块内存并返回空指针.

下面我们做一个梳理:

void free(*ptr)将创建的内存块释放。建议同时让相应指针设为空指针。

注意事项,在指针接收创建好的内存块首地址时,后面进行操作可能或多或少发生此指针指向改变的情况或者这些函数没有申请到内存,导致返回的为NULL指针,因此我们使用时,最好if判断一下:

二维动态数组:

学习之前所需具备的知识:指针数组:类比整型数组储存整型,字符型数组储存字符,指针数组就是储存指针的。用法为 int *arr[x]={p1 ,p2 ,p3 ….px}; 读取内存就是 **p1,**p2….**px

当我们创建多个一维数组的时候,返回的都是对应首元素指针,我们就可以用指针数组将这些指针储存,通过指针数组寻找每个数组首元素地址在通过数组连续存放原理找到这个数组的其他元素.

下图形象化:

那么我们就可以通过循环并借助指针数组来创建二维数组了:

那么我们创建正式的数组之前,我们要先创建动态指针数组,创建的方式也是和动态数组一样的,用malloc或calloc函数。这两个函数创建的是内存,指针也是内存当然也可以创建,类型声明对了就行。

为什么创建的是二级指针,打个比方,我们存储指针的地址时就要用到int**p,那么存一组指针当然也是int**arr了。

代码举例:

那么我们来通过这个图,将注意的事项都仔细说一遍:

第一:判断指针是否为空指针。这里会用到循环创建多个内存块,如果哪个内存没有创建到就应该及时停止代码的运行,防止后面出错。以及后面的赋值和打印同样的。那么这里我用到了一个assert.h的断言函数,当不满足条件时就会退出程序并显示问题存在的行数。这是最严谨的代码,我们需要注意学会并运用。

第二:及时释放内存。这里我们要先借助arr循地址来释放几个动态数组,再通过free释放arr。不能交换,不然找不到我们的那几个动态内存了。

二维动态数组的运用:扫雷的面积自定义(大家可以看我之前发的扫雷文章),一些需要改变数组长宽的问题都是一样的。

我再次提醒大家要养成内存管理的好习惯,为后面的进阶做铺垫,打下坚实基础。

另外,祝大家新年快乐,点点赞吧QWQ,你们的点赞和关注是我更新的最大动力。