一篇文章,弄懂动态内存管理 目录为什么要有动态内存管理malloccallocrealloc柔性数组柔性数组的特点柔性数组的使用柔性数组的好处动态内存管理为什么要有动态内存管理我们目前已知道的开辟内存空间的方式如下inta4;//向栈区申请四个字节的空间chari[10]{0};//向栈区申请连续的10个字节空间上述申请空间的方式有如下特点申请后空间的大小是固定的数组在声明空间大小后空间的大小就不能更改了可是在我们运行程序时很多时候内存的大小是要在运行程序的过程中才知道的这就意味着对提前申请的静态空间可能造成空间的浪费或者溢出。于是c语言就引用了动态内存管理允许程序员实时申请或者释放内存以达到高效利用。mallocvoid*malloc(size_tsize)功能向堆区申请一块连续的空间并返回这块空间的起始地址。参数size:表示要申请空间的字节数大小若申请成功则返回这块空间的起始地址。若申请失败比如内存不足则返回一个空指针NULL因此在使用时要注意检查返回值是否为NULL由于返回值的类型是void*,因此接受指针还要根据数据类型来定义注意事项若参数size为0则是标准的未定义行为可能会导致错误。要包含头文件stdlib.h功能用来释放之前动态内存函数realloc,calloc,malloc)申请的动态空间使用前要包含头文件stdlib.h参数ptr指向要释放空间的起始地址注意事项若ptr指向的内存空间是静态的则该行为未定义若ptr是空指针NULL那么free函数什么也不会做在释放完ptr指向的动态空间后一般把该指针置为NULLcallocvoid*calloc(size_tnum,size_tsize);功能在堆区上申请num个大小为size个字节的空间并把每个空间的每个字节初始化为0其他与malloc类似唯一的区别是calloc会把申请空间的每一个字节初始化为0reallocrealloc的出现让动态内存分配更灵活当我们发现过去申请的内存过大或者过小可以通过realloc重新进行动态内存分配void*realloc(void*ptr,size_tsize);功能重新分配原有内存块的大小在不丢失原有内存块中数据的前提下合理扩大或缩小内存。参数ptr指向要调整内存块的起始地址如果ptr是空指针NULL则realloc的功能类似malloc。size表示要分配内存的大小单位字节返回值成功返回该内存块的起始地址该指针可能和ptr相同或者不同失败返回NULL指针并且保持原来内存块不变。注意事项realloc在追加空间时有以下两种情况当原有空间充足时会直接在原有空间后面追加空间数据内存不变返回传入的地址。当原有空间不够时候会在堆区中寻找内存足够的空间并返回新地址有如下过程开辟空间将原有数据拷贝到新的空间保证数据不丢失自动释放旧空间返回新空间的起始地址柔性数组结构中最后一个元素允许是未知大小的数组这就叫作柔性数组成员structst_type{inta;intarr[];//柔性数组成员}柔性数组的特点结构中柔性数组前至少有一个成员使用sizeof计算结构内存大小时柔性数组不参与内存计算包含柔性数组的结构使用malloc()函数进行内存的动态内存分配并且分配的大小应该大于结构的大小以适应柔性数组的预期大小。柔性数组的使用#includestdlib.hstructS{inta;intarr[];};intmain(){structS*p(structS*)maalloc(sizeof(structS)5*sizeof(int));for(inti0;i5;i){p-arr[i]i1;}structS*ptrrealloc(p,sizeof(structS)10*sizeof(int));pptr;ptrNULL;for(inti5;i10;i){p-arr[i]i1;free(p);pNULL;}return0;}上述代码也可以通过非柔性数组的方式实现#includestdlib.hstructS{inta;int*ps;};intmain(){structS*p(structS*)malloc(sizeof(structS));p-a100;int*pp(int*)malloc(p-a*sizeof(int));p-pspp;ppNULL;for(p-a0;p-a100;p-a){p-ps[p-a]p-a1;}free(p-ps);p-psNULL;free(p);pNULL;return0;}柔性数组的好处从上面的写法对比可以总从上面的写法对比可以总结出柔性数组的好处。第一个好处方便内存释放如果我们的代码是在一个给别人用的函数中你在里面做了二次内存分配并把整个结构体返回给用户。用户调用free可以释放结构体但是用户并不知道这个结构体内的成员也需要free所以你不能指望用户来发现这件事。因此如果我们把结构体的内存以及其成员要的内存一次性分配好了并返回给用户一个结构体指针用户做一次free就可以把所有的内存也给释放掉。第二个好处有利于访问速度连续的内存有益于提高访问速度也有益于减少内存碎片。其实我个人觉得也没多高了反正你跑不了要用做偏移量的加法来寻址