一、malloc回忆
我在上节中讲了malloc,其作用为在堆区开辟一块内存;开辟内存的单位为字节,返回开辟内存的起始位置。其函数原型为:void* malloc(size_t byte)。
同时我们也知道在堆区开辟一个内存空间,只要这个程序不结束这个空间会一直存在(很多人想怎么可能程序不结束,别忘了很多程序都是7乘24小时不间断运行),所以我们需要在使用完后用free释放掉内存空间,并且把开辟内存的起始位置指针置为NULL。
二、calloc讲解
1、区别
除了malloc在堆区申请动态内存外,calloc也行,但是他们两个稍有区别,我们从calloc的函数原型入手--> void* calloc( size_t num , size_t size ) 。同时calloc在堆区开辟内存后会把内存字节都置为0。因此我们可以分析出有以下两个区别。
函数原型中参数不同: calloc原型函数中含有需指明含有多少个元素(size_t num),每个元素的大小(size_t size);而malloc仅仅只需要说明其开辟多少个字节(byte)即可。
内存空间是否会初始化:calloc 在堆区开辟空间后会将开辟空间每个字节都置为0。而malloc则不会(其开辟内存空间为随机值);所以我们可以说: calloc ==malloc +memset;将malloc开辟后的空间使用memset函数将其置于0。简单来说就是malloc不初始化开辟内存空间;calloc初始化内存空间。
2、相同
- 同样在开辟后进行判断是否开辟成功,如果没开辟成功返回NULL。
- 使用完动态内存空间后,需要将其释放(free),同时将记录起始位置指针置为空指针。
三、realloc讲解
其实在上述讲解中,malloc与calloc都是在堆区开辟出一块固定大小的内存空间,如果需要调整的话则需要用到realloc。我们先看一下其函数原型:void* realloc(void* ptr,size_t num)。
所以只需要将需要更改内存的起始位置指针以及更改后内存大小(byte)给realloc即可。
但是存在三种情况
所需要增加的空间 如果在已开辟空间后面有足够的空间 则直接在原有空间后面开辟。
所需要增加的空间 如果在已开辟空间后面无足够的空间 则会将原有的数据复制下来另寻一块地址,同时也会将原来的那块地址释放,这个都是在realloc内部进行,我们无需多管。
- 所需要缩下的空间 就直接在已开辟空间后面直接缩下就行。
四、注意事项
- 如果malloc、calloc开辟0个字节空间,C语言未定义,取决于编译器。
- 用free释放空指针时,则什么都不释放,编译不会报错。
- 不能对NULL指针进行解引用操作,如不对开辟内存后进行判断是否开辟成功,就有可能在未开辟成功的情况下解引用。
- 对动态内存开辟空间的越界访问,如动态内存开辟的空间都是字节个数,而被认为是整形个数使用则可能造成越界访问。
- 对非动态内存空间进行free释放则会无法编译。
- 使用free释放动态内存的一部分(无法编译),所以在开辟动态内存时,应记住内存的起始位置。
- 对同一块动态内存进行多次释放,如果在第一次进行释放后置为空指针,后面释放不会报错无影响,但是未置于空指针进行再次释放就不行(无法编译)!
- 如果忘记释放动态空间,虽然编译器不会报错,但是会造成内存泄露。