下面我们来看calloc函数是用来干嘛的,calloc函数跟前面的函数的区别是会把申请的内存置为0。就是直接默认值为0,我们分配内存中数组与初始化的元素为0.如下图代码
而上面的malloc函数申请出来的内存如果没有初始化,打印出来的值可能是一个什么负八千多万的值之类的,这个值不对就是因为没有初始化内存。
但calloc函数用的并不多,因为如果用malloc函数的话可以写完再用个循环处理一下也能解决,或者不用循环也能处理,比如用别的函数把内存置0,也很方便。
但如果遇到本来就需要把内存置0的时候,用calloc的效率会高一些。
接下来看realloc函数,它是用来扩容的
。举例比如你估计你需要使用n个格子内存,但你预估不足,实际上你需要使用2n个格子的内存。其实在很多事情应用上都没办法做到预估完全的,所以就需要扩容。而在扩大容量的过程里,就类似于搬家,第一步先要有一个新的房子,第二步要将原来家里的东西搬过去,第三步将旧房子卖了或是处理了,第四步将家庭地址更新变成现在的房屋新地址。
当然也可以使用malloc函数来扩容,第一步先n*sizeof来申请新的内存,第二步利用循环把原来的n个数据复制过来,第三步把原来的p给free掉,第四步更新为现在新的内存地址。就是这个过程比较麻烦。
所以我们可以利用realloc函数统一解决这些步骤,使用方法如下
即realloc()里要包含两个参数,原来内存不够用的p和新申请的内存大小,前者用来转移数据和释放旧的内存。而realloc前面仍然有个返回值,所以我们需要定义一个变量来接收这个新地址的返回值,以便于后面访问新地址,原来的地址已经释放不能访问了。所以这个新地址很有可能(但并不绝对)和原来的旧地址是不一样的地址,这就跟操作系统的内存管理策略有关了。看你所在的区域,例如城市里搬家就和原住址不一样,但农村里扩建院子就在原本家里的地方旁边空地上盖。但这个地址变不变是相对的不是绝对的,在这个地方不变不代表在另一个地方不变,但变不变跟我们关系也不大,我们要做的就是接受这个新地址并且用新的地址。
例如在x64(x64指的是64位操作系统)下是一样的地址
这里补充一个知识点
但在x86下就变了
也有地址仍然一样的,这里有可能是因为这个内存没有使用,就是系统有可能采取一种叫延迟内存分配的,就是你申请了内存但没有用,那么系统就还会把这个没用过的内存给你。但你要是用了,系统就会找新的内存分配给你。后面在Linux底下会有一个名词叫写实拷贝,就是只有你去改写了它的时候才会去拷贝数据。
综上所述,realloc函数扩容最要注意的是接收新地址。
最后在回顾一下动态内存,当你需要申请内存的时候,就叫malloc来说需要分配多少内存,之后malloc就会把它的首地址返回给你,你来接收它的首地址,然后就可以把它当做一个数组来使用了。