Distinguish between malloc、calloc and realloc

在程序的执行期间,分配内存的区域有三种:静态存储区、堆(heap)内存和栈(stack)内存。

(1)静态存储区在程序编译时就已经分配好了,这块内存在程序运行期间都会存在。如全局变量、static变量。

(2)堆内存是由程序员控制。在分配堆内存时,由程序员跟踪所分配的内存何时需要、何时不再需要,合理释放该空间,防止内存泄露,以便于日后重新用它们。如果程序员没有手动释放内存,在程序关闭之后OS会协助释放。

(3)栈内存的空间分配给函数的参数和本地变量,在执行完该函数后,存储参数和本地变量的内存就会被释放。栈内存效率高但是内存容量有限。


三个函数的声明

void* malloc(size_t _Size);

//参数_Size表示新开辟的空间大小,单位是字节

void* calloc(size_t _NumOfElements,size_t _SizeOfElements);

//参数_NumOfElements表示开辟空间的元素 的个数,_SizeOfElements表示开辟空间的每个元素大小字节

void* realloc(void *_Memory,size_t _NewSize);

//参数_Memory表示原有空间的地址,_NewSize表示重新申请的地址长度

 

这三个函数都在stdlib.h库函数内,三者的返回值都是请求系统分配的地址,如果请求失败就返回NULL。

(1)malloc函数

在内存的动态存储中分配一块长度为size字节的连续区域,参数size为需要内存空间的长度,返回该区域的首地址。

(2)calloc函数

在内存的动态存储中分配每个单位元素长度为_SizeOfElements字节,单位元素个数为_NumOfElements个,一共_SizeOfElements*_NumOfElements字节大小的连续地址空间。

(3)realloc函数

给一个已经分配了地址的指针重新分配空间,参数_Memory为原有的空间地址,_NewSize是重新申请的地址长度。

 

☆区别

①malloc和calloc:函数malloc不能初始化所分配的内存空间,但是calloc可以。 如果malloc函数分配的内存空间原来没有被使用过,则其中的每一位可能都是0,反之如果这部分内存曾经被使用分配过,则其中可能遗留有各种各样的脏数据。因此,在使用malloc函数一般伴随使用memset函数。

 

②calloc函数的初始化:calloc函数会将所分配的内存空间中的每一位都初始化为0。也就是说,如果你是为字符char类型或者整数int类型分配内存,那么这些元素都会初始化为整型的0;如果你是为指针类型的元素分配内存,那么这些元素通常会被初始化为空指针;如果你为浮点型数据分配内存,那么这些元素会被初始化浮点型的0.0。

 

③三个函数的返回值是void*型,void*型表示未确定类型的指针。C/C++规定,void*可以强制转换为任何其它类型的指针。

 

④realloc函数可以对给定指针所指的空间进行缩小和扩大。无论是缩小或者扩大,对于原来空间的数据不会改变。如果缩小,则有可能会丢失部分数据。但是!realloc函数并不能够保证前后的地址一致,很有可能指针指向一个新的地址。

 

⑤realloc函数当进行扩大内存操作时,realloc会首先试图在原来的内存后面进行扩大。如果原来的内存后面的扩存够,则首地址不会变化,直接扩容成功;如果原来的内存后面的扩存不够,那么会在堆内存从头往后找,直到找到合适的区域为止,然后将原来内存区域的数据拷贝到新地址内存区域,首地址发生了变化并且数据发生了移动,数据的地址被改变。

上一篇:拨开由问题《linux下malloc最大可申请的内存》带来的重重疑云


下一篇:数据结构C语言—线性表【顺序存储】顺序表(malloc动态分配实现)