1. malloc,calloc,realloc的原型和功能
1)malloc- 动态内存分配:memory allocation
函数原型--- void *malloc(size_t size);
void* 表示未确定类型的指针,void *可以指向任何类型的数据,是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据。
C,C++规定,void *类型可以强制转换为任何其它类型的指针。
功能--- 向系统申请分配size个字节大小的内存空间。
返回值 --- 如果分配成功,返回指向被分配内存的指针,否则返回空指针NULL。
void free(void *ptr); free()函数与malloc()函数配对使用,释放malloc函数申请的动态内存。
注:如果ptr是NULL指针,那么free对ptr无论操作多少次都不会出问题。如果ptr不是NULL指针,那么free对ptr连续操作两次就会导致程序运行错误。
---- malloc和new:new返回指定类型的指针,并且可以自动计算所需要的大小。int *p = new int;
而malloc则必须要由我们计算字节数,并且在返回后强制转换为实际类型的指针。int *p = (int *)malloc(sizeof(int)*100); //连续内存空间
---- malloc函数的实质所在:类似于首次适应算法
系统有一个将可用的内存块连接在空闲链表中。当调用malloc函数时,它沿空闲链表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块
一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块返回到
空闲链表上。调用free函数时,将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段
那么空闲链上可能没有可以满足用户要求的片段了。于是malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻
的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针。
因此在调用malloc函数动态申请内存块时,一定要进行返回值的判断。
2)calloc- 动态内存分配并清零
函数原型--- void *calloc(size_t n,size_t size);
功能--- 在内存的动态存储区中分配n个长度为size的连续空间,并将其中的内容置为0。动态分配完后,初始化该内存空间为0。
返回值 --- 函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
3)realloc - 动态内存调整
函数原型 --- void *realloc(void *addr,size_t newsize); //新的大小要大于原来的大小,否则会导致数据丢失。
功能--- 先判断当前的指针是否有足够的连续存储空间,如果有,扩大addr所指向的空间,并返回addr。
如果没有,重新按照指定的newsize大小分配空间。将addr指向的原有数据从头到尾拷贝到新分配的内存区域,
释放原来addr指向的内存区域(原来的指针是自动释放-realloc成功,不需要free),同时返回新分配的内存区域的首地址。
返回值--- 若重新分配成功,返回指向被分配内存的指针,否则返回空指针NULL。
注意:
---- realloc失败的时候,返回NULL。
---- realloc失败的时候,原来的内存不改变,不会释放也不会移动。
---- 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址,假如原来的内存
后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存
的地址。
---- 如果newsize为0,效果等同于free().
---- 传递给realloc的指针必须是先前通过malloc(),calloc(),或realloc()分配的。
---- 传递给realloc的指针可以为空,等同于malloc().
2. malloc和calloc对比
#include "stdafx.h"
#include <stdio.h>
int main()
{
char *pch=NULL;
pch=(char *)malloc(3*sizeof(char));
printf("%s\n",pch);
int *pn=NULL;
pn=(int *)calloc(5,sizeof(int));//在动态存储区中分配10个长度为char长度的连续存储区间
for(int i=0;i<5;i++)
{
printf("%d\t",pn[i]);
}
printf("\n");
free(pch);
free(pn);
system("pause");
return 0;
}
输出结果显示:
代码中我们可以看出:
使用malloc函数动态分配了3个bytes的空间,但是没有初始化,输出是乱码。
使用colloc函数动态分配了5个长度是sizeof(int)的存储空间,并初始化为0,输出0.
3. malloc和realloc对比
#include "stdafx.h"
#include <stdio.h>
int main()
{
int *pn=NULL;
pn=(int *)malloc(5*sizeof(int));//开始分配20个字节
printf("Initial address is %d\n",(int)pn);
pn=(int *)realloc(pn,10*sizeof(int));//重新分配40个字节,需要检测该地址后是否有连续的40个bytes的内存空间
printf("End address is %d\n",(int)pn);
free(pn);
system("pause");
return 0;
}
输出结果显示:
可以看出两个地址是相同的,所以在使用realloc重新分配内存的时候有足够的连续存储空间。
4. realloc改变已分配的内存大小
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int *p = NULL;
p = (int *)malloc(5*sizeof(int));//开始分配20个字节
printf("Initial address is %d\n",(int)p);
p = (int *)realloc(p,1000*sizeof(int));//重新分配4000个字节,需要检测该地址后是否有连续的4000个bytes的内存空间
printf("End address is %d\n",(int)p);
free(p);
system("pause");
return 0;
}
输出结果显示:
扩大size之后,发现两个地址不一样了,证明开始指针p所指向的内存区域已经没有足够的空间了,重新分配内存后指向发生了变化。